题目戳我

\(\text{Solution:}\)

题目标签是\(dp,\)但是纯暴力打表找规律可以有\(65\)分。

首先是对于\(O(2^{nm}*nm)\)的暴力搜索,显然都会。

考虑几条性质:

  • 每一条由左下到右上的对角线需要非严格单调递减。

  • 若\(a[i][j-1]=a[i-1][j]\)则以\(a[i][j]\)为左上角的矩阵填的数必须相等。

证明:

对于第一条,若不满足这条性质,则必然存在一个路径,\(R\to 1,D\to 0\)使得其不满足题意。

对于第二条,首先满足\(R\to x,D\to x,\)则对于后面的所有路径,若有一个不相等的则必然存在一条路径\(D\to Big\)或\(R\to Small\)使得题目不成立。

于是,设\(a[i][j]\)表示第\(j\)列\(i\to n\)行数字的状压结果,\(b[i][j]\)表示以\((i,j)\)为左上角的矩阵的数字是不是相等。

考虑每次填数完毕就判断一次。若矩阵相等,则\(\text{b[i][j]=b[i][j+1]&&(a[i][j+1]>>1)==a[i+1][j]}\)

然后对角线是\(\text{x<n&&y>1&&g[x][y]==g[x+1][y-1]&&!b[x+1][y](False)}\)

代码中保证只有上一次填了\(1\)下一次才能继续填。否则必须填\(0\).从而起到了剪枝的效果。

于是可以打表,继续找规律:

int A[9][9]= {
{0,0,0,0,0,0,0,0,0},
{0,2,4,8,16,32,64,128,256},
{0,0,12,36,108,324,972,2916,8748},
{0,0,0,112,336,1008,3024,9072,27216},
{0,0,0,0,912,2688,8064,24192,72576},
{0,0,0,0,0,7136,21312,63936,191808},
{0,0,0,0,0,0,56768,170112,510336},
{0,0,0,0,0,0,0,453504,1360128},
{0,0,0,0,0,0,0,0,3626752},
};

观察一下,上半个矩阵中,有很多值满足\(a[i][j]=a[i][j-1]*3.\)

所以,特判掉\(n=m\)的情况后,直接调用\(A(n,n+1)\)并使用快速幂即可。

#include<bits/stdc++.h>
using namespace std;
int n,m,R=10879488;
int A[9][9]= {
{0,0,0,0,0,0,0,0,0},
{0,2,4,8,16,32,64,128,256},
{0,0,12,36,108,324,972,2916,8748},
{0,0,0,112,336,1008,3024,9072,27216},
{0,0,0,0,912,2688,8064,24192,72576},
{0,0,0,0,0,7136,21312,63936,191808},
{0,0,0,0,0,0,56768,170112,510336},
{0,0,0,0,0,0,0,453504,1360128},
{0,0,0,0,0,0,0,0,3626752},
};
const int mod=1e9+7;
inline int add(int x,int y) {
return (x+y)%mod;
}
inline int mul(int x,int y) {
return 1ll*x*y%mod;
}
namespace P3 {
inline int qpow(int x,int y) {
int res=1;
while(y) {
if(y&1)res=mul(res,x);
x=mul(x,x);
y>>=1;
}
return res;
}
void solve() {
if(n>m)swap(n,m);
if(n==m)printf("%d\n",A[n][m]);
else {
if(n==1) {
printf("%d\n",qpow(2,m));
return;
}
int c=m-n;
if(n<8)R=A[n][n+1];
printf("%d\n",mul(R,qpow(3,c-1)));
}
}
}
namespace Biao {
int a[13][13],g[30][30],ans=0;
bool b[100][100];
bool check(int x,int y) {
a[x][y]=a[x+1][y]|(g[x][y]<<(n-x));
if(y==m)b[x][y]=1;
else b[x][y]=b[x][y+1]&&(a[x][y+1]>>1)==a[x+1][y];
if(x<n&&y>1&&g[x][y]==g[x+1][y-1]&&!b[x+1][y])return false;
return true;
}
void dfs(int x,int y) {
if(y<1) {
dfs(x-1,m);
return;
}
if(x<1) {
ans++;
return;
}
if(x==n||y==1||g[x+1][y-1]==1) {
g[x][y]=1;
if(check(x,y))dfs(x,y-1);
}
g[x][y]=0;
if(check(x,y))dfs(x,y-1);
}
void solve() {
ans=0;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(g,0,sizeof(g));
if(n>m)swap(n,m);
dfs(n,m);R=ans;
}
}
int main() {
scanf("%d%d",&n,&m);
P3::solve();
return 0;
}

参考:https://www.luogu.com.cn/blog/2003ok/solution-p5023 Lisy_03 的博客

(侵删)

总结:数据范围小所想到的状压\(dp\)并不一定正确,在不会正解的情况下先写暴力打表。

【题解】NOIP2018 填数游戏的更多相关文章

  1. [Noip2018]填数游戏

    传送门 Description 耳熟能详,就不多说了 Solution 对于一个不会推式子的蒟蒻,如何在考场优雅地通过此题 手玩样例,发现对于 \(n=1\) , \(ans=2^m\) .对于 \( ...

  2. NOIP2018 填数游戏 搜索、DP

    LOJ 感觉这个题十分好玩于是诈尸更博.一年之前的做题心得只有这道题还记得清楚-- 设输入为\(n,m\)时的答案为\(f(n,m)\),首先\(f(n,m)=f(m,n)\)所以接下来默认\(n \ ...

  3. 【比赛】NOIP2018 填数游戏

    打表找规律.... #include<bits/stdc++.h> #define ui unsigned int #define ll long long #define db doub ...

  4. @NOIP2018 - D2T2@ 填数游戏

    目录 @题目描述@ @题解@ @代码@ @题目描述@ 小 D 特别喜欢玩游戏.这一天,他在玩一款填数游戏. 这个填数游戏的棋盘是一个 n×m 的矩形表格.玩家需要在表格的每个格子中填入一个数字(数字 ...

  5. 【逆向笔记】2017年全国大学生信息安全竞赛 Reverse 填数游戏

    2017年全国大学生信息安全竞赛 Reverse 填数游戏 起因是吾爱破解大手发的解题思路,觉得题挺有意思的,就找来学习学习 这是i春秋的下载链接 http://static2.ichunqiu.co ...

  6. luogu P5023 填数游戏

    luogu loj 被这道题送退役了 题是挺有趣的,然而可能讨论比较麻烦,肝了2h 又自闭了,鉴于CSP在即,就只能先写个打表题解了 下面令\(n<m\),首先\(n=1\)时答案为\(2^m\ ...

  7. UOJ#440. 【NOIP2018】填数游戏 动态规划

    原文链接www.cnblogs.com/zhouzhendong/p/UOJ440.html 前言 菜鸡选手到省选了才做联赛题. 题解 首先我们分析一下性质: 1. 假如一个格子是 0,那么它的右上角 ...

  8. [NOIP2018 TG D2T2]填数游戏

    题目大意:$NOIP2018\;TG\;D2T2$ 题解:在skip2004的博客基础上修改的,也是暴搜. 说明一下把vector改成数组并不可以通过此题,记录. 结论:在$m>n+1$时答案为 ...

  9. JZOJ5965【NOIP2018提高组D2T2】填数游戏

    题目 作为NOIP2018的题目,我觉得不需要把题目贴出来了. 大意就是,在一个n∗mn*mn∗m的010101矩阵中,从左上角到右下角的路径中,对于任意的两条,上面的那条小于下面的那条.问满足这样的 ...

随机推荐

  1. ES6--let,解构赋值,promise && ES7--async

    ES-->IE10.Google.火狐 ES6 let 声明的关键字 不能重复声明 块级作用域 <input type="button" value="1&q ...

  2. MonoBehaviour生命周期与对象数据池应用

    预热游戏对象: tempObject = Instantiate(cubePrefab) as GameObject ; tempObject .SetActive( false ); 游戏对象tem ...

  3. P1306 斐波那契公约数(ksm+结论)

    题目描述 对于Fibonacci数列:1,1,2,3,5,8,13......大家应该很熟悉吧~~~但是现在有一个很“简单”问题:第n项和第m项的最大公约数是多少? Update:加入了一组数据. 输 ...

  4. 未读消息(小红点),前端与 RabbitMQ实时消息推送实践,贼简单~

    前几天粉丝群里有个小伙伴问过:web 页面的未读消息(小红点)怎么实现比较简单,刚好本周手头有类似的开发任务,索性就整理出来供小伙伴们参考,没准哪天就能用得上呢. 之前在 <springboot ...

  5. 跟着尚硅谷系统学习Docker-【day04】

    day04-20200716   p18.docker容器数据卷   docker容器中的数据,做持久化. 容器关闭以后容器内的数据就没有了. 保存到数据库或者服务器宿主机里面.   作用:容器间可以 ...

  6. 09. jenkins配置不同用户显示不同视图

    jenkins配置不同用户显示不同视图 一.新建用户 1.1 新建用户 Manage Jenkins -> Manage Users -> 新建用户     1.2 我创建了三个用户,分别 ...

  7. 原生js实现jquery的siblings()

    Element.prototype.siblings = function(callback){ var siblingElement = []; var parentAllElement = []; ...

  8. 单应用模式 - Layuiadmin单页版放入TP6.0的部署方案

    thinkphp6.0.3单应用模式.layuiadmin1.4.0单页版,不需要tp的视图驱动 1. 复制 src.start 两个文件夹 2. 粘贴到 thinkphp 的 public 目录下 ...

  9. jmeter服务器监控磁盘IO、网络-PerfMon Metrics Collector

    1.jmeetr客户端安装jp@gc - PerfMon Metrics Collector 先安装jmeter-plugins 启动jmeter ——> 客户端选项 ——> jmeter ...

  10. IT行业程序开发如何

    学习程序开发怎么样,由于软件开发涉及到的知识结构比较丰富,所以学习软件开发通常需要一个系统的学习过程.如果未来要想专业从事软件开发工作,那么可以按照以下步骤学习软件开发技术: 第一:从计算机操作系统开 ...