传送门

Description

耳熟能详,就不多说了

Solution

对于一个不会推式子的蒟蒻,如何在考场优雅地通过此题

  1. 手玩样例,发现对于 \(n=1\) , \(ans=2^m\) 。对于 \(n=2\) , \(ans=4\times 3^{m-1}\) 。或者干脆打出 \(n,m\le 3\) 的表

  2. 肉眼观察法,发现似乎有 \(f(n,m+1)=3f(n,m)\),但这并不是正确的,但如果你仅仅是这么认为了,你仍然能够获得很多分数

  3. 想结论,都是特别特别显然的那种:

  • \(f(n,m)=f(m,n)\) ,因而只要考虑 \(n\le m\) 的情况

  • 因为每步向右或向下,所以可按照步骤,把图分成一条条从左下到右上的斜线,对于单个格子进行考虑,发现每条斜线上的数单调不增(所以呢,你就可以通过枚举每条斜线在哪个位置开始变为\(0\)就可以了,简单打表)

  • 为了检验图的正确性,我们还需要发掘合法填数方式的更多性质:

    考虑怎样造成不合法,存在两条路径,它们在某个位置不合法了,那么它们之前路径对应的01串相同,且上一个位置相同,在不合法的这一步中,大的路径走了 \(0\) ,小的路径走了 \(1\) 。

    这启发我们,对于一张合法的图,如果某个点,存在两条到达它的路径对应相同的01串,那么它的后继相同,我们令这样的点叫\(A\)点,一个点是\(A\)点当且仅当它的前驱中有A点或者它的前驱的数相同

  1. 有了这么多的性质,我们发现其实可以打表拿很多分了,于是开始愉快地搜索,按照斜线一条条地搜,边搜边更新当前图的点中\(A\)类的点,同时,每条斜线上只有 \(0\) 和 \(1\) 的交界处可能导致不合法,判断一下它的上一个点是否是\(A\)类点就可以了
  2. 打出表了,发现结论 \(f(n,m+1)=3f(n,m),m>n\) !于是就很开心地过了
  3. 这个搜索是真的快,极限数据 \(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!

[Noip2018]填数游戏的更多相关文章

  1. NOIP2018 填数游戏 搜索、DP

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

  2. 【题解】NOIP2018 填数游戏

    题目戳我 \(\text{Solution:}\) 题目标签是\(dp,\)但是纯暴力打表找规律可以有\(65\)分. 首先是对于\(O(2^{nm}*nm)\)的暴力搜索,显然都会. 考虑几条性质: ...

  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. JZOJ5965【NOIP2018提高组D2T2】填数游戏

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

  8. NOIP2018 Day2T2 填数游戏

    下面先给出大家都用的打表大法: 首先我们可以发现 \(n \le 3\) 的情况有 \(65pts\),而 \(n\) 这么小,打一下表何乐而不为呢?于是我写了一个爆枚每个位置再 \(check\) ...

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

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

随机推荐

  1. 另一种缓存,Spring Boot 整合 Ehcache

    用惯了 Redis ,很多人已经忘记了还有另一个缓存方案 Ehcache ,是的,在 Redis 一统江湖的时代,Ehcache 渐渐有点没落了,不过,我们还是有必要了解下 Ehcache ,在有的场 ...

  2. Redis 分析部分功能所解决的问题

    前言:说到缓存,大家都会想到redis,而redis中又有各种眼花缭乱的功能,今天就来看看这些功能能解决的问题. Redis官方简介 Redis是一个基于BSD开源的项目,是一个把结构化的数据放在内存 ...

  3. Mvc中模拟模型

    如题,每次研究前台技术都要建数据库.连接,还遇到VS各种版本问题,太麻烦. 写这么一个东西,模仿后台Model,上课的时候研究代码层面的内容.甚好. 数据库类: class myDatabase { ...

  4. 转:Oracle中SQL语句执行过程中

    Oracle中SQL语句执行过程中,Oracle内部解析原理如下: 1.当一用户第一次提交一个SQL表达式时,Oracle会将这SQL进行Hard parse,这过程有点像程序编译,检查语法.表名.字 ...

  5. Python Django 实现简单注册功能

    Python Django 实现简单注册功能 项目创建略,可参考前期文档介绍. 目录结构如下 编辑views.py from django.shortcuts import render # Crea ...

  6. 集成学习 - Bagging

    认识 Bagging 的全称为 (BootStrap Aggregation), 嗯, 咋翻译比较直观一点呢, 就有放回抽样 模型训练? 算了, 就这样吧, 它的Paper是这样的: Algorith ...

  7. javascript之DOM选择符

    javascript库中最常用的一项功能,就是根据CSS选择符选择与某个模式匹配的DOM元素.实际上jQuery的核心就是通过css选择符查询DOM文档取得元素的引用,从而抛开了getElementB ...

  8. PHP redis 常用操作

    //在列表头部插入一个值one,当列表不存在时自动创建一个列表,key1为列表名 $redis->lpush("key1", "one"); //在列表尾 ...

  9. Centos7防火墙firewalled基本使用

    firewalld支持动态更新技术并加入了区域(zone)的概念.简单来说,区域就是firewalld预先准备了几套防火墙策略集合(策略模板),用户可以根据生产场景的不同而选择合适的策略集合,从而实现 ...

  10. JavaScript中eval函数的用法

    1. eval函数会计算传给的字符串, 并把作为脚本代码来执行. eval(str) 此函数接受一个字符串作为参数,并把str当做一段JavaScript脚本代码来执行,如果str执行结果返回一个值则 ...