【题解】NOIP2018 填数游戏
\(\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 填数游戏的更多相关文章
- [Noip2018]填数游戏
传送门 Description 耳熟能详,就不多说了 Solution 对于一个不会推式子的蒟蒻,如何在考场优雅地通过此题 手玩样例,发现对于 \(n=1\) , \(ans=2^m\) .对于 \( ...
- NOIP2018 填数游戏 搜索、DP
LOJ 感觉这个题十分好玩于是诈尸更博.一年之前的做题心得只有这道题还记得清楚-- 设输入为\(n,m\)时的答案为\(f(n,m)\),首先\(f(n,m)=f(m,n)\)所以接下来默认\(n \ ...
- 【比赛】NOIP2018 填数游戏
打表找规律.... #include<bits/stdc++.h> #define ui unsigned int #define ll long long #define db doub ...
- @NOIP2018 - D2T2@ 填数游戏
目录 @题目描述@ @题解@ @代码@ @题目描述@ 小 D 特别喜欢玩游戏.这一天,他在玩一款填数游戏. 这个填数游戏的棋盘是一个 n×m 的矩形表格.玩家需要在表格的每个格子中填入一个数字(数字 ...
- 【逆向笔记】2017年全国大学生信息安全竞赛 Reverse 填数游戏
2017年全国大学生信息安全竞赛 Reverse 填数游戏 起因是吾爱破解大手发的解题思路,觉得题挺有意思的,就找来学习学习 这是i春秋的下载链接 http://static2.ichunqiu.co ...
- luogu P5023 填数游戏
luogu loj 被这道题送退役了 题是挺有趣的,然而可能讨论比较麻烦,肝了2h 又自闭了,鉴于CSP在即,就只能先写个打表题解了 下面令\(n<m\),首先\(n=1\)时答案为\(2^m\ ...
- UOJ#440. 【NOIP2018】填数游戏 动态规划
原文链接www.cnblogs.com/zhouzhendong/p/UOJ440.html 前言 菜鸡选手到省选了才做联赛题. 题解 首先我们分析一下性质: 1. 假如一个格子是 0,那么它的右上角 ...
- [NOIP2018 TG D2T2]填数游戏
题目大意:$NOIP2018\;TG\;D2T2$ 题解:在skip2004的博客基础上修改的,也是暴搜. 说明一下把vector改成数组并不可以通过此题,记录. 结论:在$m>n+1$时答案为 ...
- JZOJ5965【NOIP2018提高组D2T2】填数游戏
题目 作为NOIP2018的题目,我觉得不需要把题目贴出来了. 大意就是,在一个n∗mn*mn∗m的010101矩阵中,从左上角到右下角的路径中,对于任意的两条,上面的那条小于下面的那条.问满足这样的 ...
随机推荐
- package_ios
PlistBuddy简单使用 https://www.jianshu.com/p/2167f755c47e xcodebuild 命令 https://www.jianshu.com/p/c32263 ...
- Shader HLSL片段说明
在编写顶点着色器或者片段着色器时,需要用到CG或者HLSL语言,这里翻译unity官网的信息. 编译指令 #pragma vertex name - 编译函数名成vertex shader #prag ...
- Palindrome subsequence(区间dp+容斥)
In mathematics, a subsequence is a sequence that can be derived from another sequence by deleting so ...
- 2019HNCPC C Distinct Substrings 后缀自动机
题意 给定一个长度为n字符串,字符集大小为m(1<=n,m<=1e6),求\(\bigoplus_{c = 1}^{m}\left(h(c) \cdot 3^c \bmod (10^9+7 ...
- 题解 洛谷P3799 【妖梦拼木棒】
一道水题 (还是做了一个小时,我太菜了 基本思路: 题里面说,4根棍子拼成一个正三角形(等边三角形) 若设这四根棍子长度为\(a,b,c,d\)且\(a≥b>c≥d\) 那很容易得到 (真的很容 ...
- Linux命令使用教程
Linux 内核最初只是由芬兰人林纳斯·托瓦兹(Linus Torvalds)在赫尔辛基大学上学时出于个人爱好而编写的. Linux 的发行版说简单点就是将 Linux 内核与应用软件做一个打包. 目 ...
- 05_Python的文件操作
1.文件操作概述 # 文件是用于数据存储的单位通常用来长期存储设置,文件中的数据是以字节为单位进行顺序存储的 1.打开文件: f = open("xxx") 或 with ...
- String字符串的最大长度是多少?
在学习和开发过程中,我们经常会讨论 short ,int 和 long 这些基本数据类型的取值范围,但是对于 String 类型我们好像很少注意它的"取值范围".那么对于 Stri ...
- SqlAnalyzer1.01 源码
源码下载:https://files.cnblogs.com/files/heyang78/SqlAnalyzer-20200529-2.rar 现有功能:不带函数允许嵌套的select ...fro ...
- Spring Boot 启动第一个页面(Spring二)
在前面的文章里我配置好了spring boot的环境,并选择STS开发工具 具体文章见:https://blog.csdn.net/qq_38175040/article/details/105481 ...