[Noip2018]填数游戏
时间:2019-11-06
本文章向大家介绍[Noip2018]填数游戏,主要包括[Noip2018]填数游戏使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
传送门
Description
耳熟能详,就不多说了
Solution
对于一个不会推式子的蒟蒻,如何在考场优雅地通过此题
手玩样例,发现对于 \(n=1\) , \(ans=2^m\) 。对于 \(n=2\) , \(ans=4\times 3^{m-1}\) 。或者干脆打出 \(n,m\le 3\) 的表
肉眼观察法,发现似乎有 \(f(n,m+1)=3f(n,m)\),但这并不是正确的,但如果你仅仅是这么认为了,你仍然能够获得很多分数
想结论,都是特别特别显然的那种:
\(f(n,m)=f(m,n)\) ,因而只要考虑 \(n\le m\) 的情况
因为每步向右或向下,所以可按照步骤,把图分成一条条从左下到右上的斜线,对于单个格子进行考虑,发现每条斜线上的数单调不增(所以呢,你就可以通过枚举每条斜线在哪个位置开始变为\(0\)就可以了,简单打表)
为了检验图的正确性,我们还需要发掘合法填数方式的更多性质:
考虑怎样造成不合法,存在两条路径,它们在某个位置不合法了,那么它们之前路径对应的01串相同,且上一个位置相同,在不合法的这一步中,大的路径走了 \(0\) ,小的路径走了 \(1\) 。
这启发我们,对于一张合法的图,如果某个点,存在两条到达它的路径对应相同的01串,那么它的后继相同,我们令这样的点叫\(A\)点,一个点是\(A\)点当且仅当它的前驱中有A点或者它的前驱的数相同
- 有了这么多的性质,我们发现其实可以打表拿很多分了,于是开始愉快地搜索,按照斜线一条条地搜,一遍搜边更新当前图的点中\(A\)类的点,同时,每条斜线上只有 \(0\) 和 \(1\) 的交界处可能导致不合法,判断以下它的上一个点是否是\(A\)类点就可以了
- 打出表了,发现结论 \(f(n,m+1)=3f(n,m),m>n\) !于是就很开心地过了
- 这个搜索是真的快,极限数据 \(n=8,m=9\) 都能在 \(0.6s\) 内过去,所以就连表都懒得打了,直接暴力就行了
Code
#include<bits/stdc++.h>
#define ll long long
#define db double
#define reg register
using namespace std;
#define dbg1(x) cerr<<#x<<'='<<(x)<<' '
#define dbg2(x) cerr<<#x<<'='<<(x)<<'\n'
#define dbg3(x) cerr<<#x<<'\n'
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
const int P=1e9+7;
int Add(int x,int y){return (x+y)%P;}
int Mul(int x,int y){return (1ll*x*y)%P;}
int fp(int x,int y){int r=1;if(y>0)for(;y;y>>=1,x=Mul(x,x))if(y&1)r=Mul(r,x);return r;}
int n,m;ll ans=0;
int Nm[20],X[20][20],Y[20][20];
bool mk[10][10],mp[10][10];
inline void getmk(int now)
{
int i,j;
for(i=X[now][1],j=Y[now][1];i&&j<=m;--i,++j)
if(i>1&&j>1)mk[i][j]=(mk[i-1][j]|mk[i][j-1]|(mp[i][j-1]==mp[i-1][j]));
}
void dfs(int now)
{
int i,j,p=Nm[now];getmk(now-1);
for(i=0;i<=p;++i)
{
if(i)mp[X[now][i]][Y[now][i]]=true;
if((i==0||i==p)||(i>0&&i<p&&!mk[X[now][i]-1][Y[now][i]]))
if(now+1==n+m)++ans;else dfs(now+1);
}
for(i=1;i<=p;++i)mp[X[now][i]][Y[now][i]]=0;
}
int main()
{
freopen("game.in","r",stdin);
freopen("game.out","w",stdout);
n=read();m=read();
if(n>m)swap(n,m);
if(n==1)return 0*printf("%d\n",fp(2,m));
int c=max(0,min(m-n,m-n-1));m-=c;
reg int i,j;
for(i=1;i<=n;++i)Nm[i]=i;
for(i=n+1;i<m;++i)Nm[i]=n;
for(i=m;i<n+m;++i)Nm[i]=n+m-i;
for(i=1;i<=n;++i)X[i][1]=i,Y[i][1]=1;
for(i=n+1;i<n+m;++i)X[i][1]=n,Y[i][1]=i-n+1;
for(i=1;i<n+m;++i)for(j=2;j<=Nm[i];++j)X[i][j]=X[i][j-1]-1,Y[i][j]=Y[i][j-1]+1;
dfs(1);printf("%lld\n",Mul(ans,fp(3,c)));
}
Blog来自PaperCloud,未经允许,请勿转载,TKS!
原文地址:https://www.cnblogs.com/PaperCloud/p/11808887.html
- NET跨平台:在Ubuntu下搭建ASP.NET 5开发环境
- 【Code】关关的刷题日记22——Leetcode 53. Maximum Subarray
- 【Java学习笔记之三十四】超详解Java多线程基础
- Codeforces 842B Gleb And Pizza【几何,水】
- Python3希尔排序
- Codeforces 842A Kirill And The Game【暴力,水】
- Wannafly模拟赛 A.矩阵(二分答案+hash)
- 【Java数据结构学习笔记之一】线性表的存储结构及其代码实现
- Comparison of Apache Stream Processing Frameworks: Part 1
- 【LeetCode】关关的刷题日记23——Leetcode 66. Plus One
- Codeforces Round #434 (Div. 2, based on Technocup 2018 Elimination Round 1)&&Codeforces 861A k-roun
- 【Java数据结构学习笔记之二】Java数据结构与算法之栈(Stack)实现
- 【Java数据结构学习笔记之三】Java数据结构与算法之队列(Queue)实现
- Comparison of Apache Stream Processing Frameworks: Part 2
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Redhat7安装docker
- 有个笔记本就可以玩一玩Hadoop
- java如何将String转换为Int
- java中如何将数组转换为List
- 从一个多层嵌套循环中直接跳出
- 如何给3个布尔变量,当其中有2个或者2个以上为true才返回true
- 比较java枚举成员使用equal还是==
- java如何将String转换为enum
- Markdown极简入门教程(1)—为什么要学习Markdown
- Markdown极简入门教程(2)—斜体和粗体
- 标题—Markdown极简入门教程(3)
- 链接—Markdown极简入门教程(4)
- 某企业授权渗透报告
- 图片—Markdown极简入门教程(5)
- 列表—Markdown极简入门教程(7)