破dp.



小松鼠开心地在树之间跳跃着,突然她停了下来。因为眼前出现了一个
拿着专克超萌小松鼠的法宝————超萌游戏机的游客!
 超萌游戏机之所以拥有这个名字,是因为它的屏幕是一个n 2的矩形。
小松鼠接过游戏机,开始了她的第一个游戏:俄罗斯方块。
 考虑到小松鼠的智商,游戏机里的方块只有下面四种,方块按顺序下落,

可以在任意时刻(甚至是下落前)对其进行不限次数的旋转操作。
 由于四种方块最小宽度都为2,因此下落的时候在水平方向上是不能够移
动的。我们称当前方块下落的过程完成了,当且仅当其再往下移动一个单
位就会与之前覆盖的方块有部分相重叠。小松鼠想要知道,在这个n 2的
游戏界面中,一共会出现多少种游戏状态。游戏状态指单次方块下落的过
程完成后,不要求游戏结束(即不要求第1行非空),且界面中出现的必须
是完整的方块。
 两种游戏状态被认为是相同的,当且仅当游戏界面中的每一个格子两种
状态下被覆盖的方块类型都相同(或都不被覆盖)。
 如下图属于两种不同的游戏状态。



NOIP2016 “西湖边超萌小松鼠” 模拟赛
出题人: ***0***
2016 年10 月18 日
一、题目概况
题目名称 GotoAndPlay  StopAllSounds  UpdateAfterEvent 
每个测试点时限1s 1s 1s
测试点数目10 10 10
每个测试点分值10 10 10
附加样例文件有有有
题目类型传统传统传统
运行内存上限256M 256M 256M
二、注意事项
保持良好的纪律,ak的同学请勿剥夺他人独立ak的权利。
评测时不开启任何优化开关。
所有题目的样例文件都已下发,不包含在题面当中。
1
2
GotoAndPlay
10月3日,在杭州市西湖景区,一只小松鼠不停地接受一道道食物,花生、
玉米、饼干,可谓来者不拒,憨态可掬的模样吸引了众多围观者...
Description 
 小松鼠终于吃撑了,她决定逃离这个地方。
 我们用一张连通图来表示整个西湖的范围,每棵容小松鼠逗留的树都用
这张图上的一个点来表示。小松鼠能够通过只跳一次互相到达的两棵树用
图上的一条无向边来连接。 
 吃撑了的小松鼠有些神志不清,每次她连跳两条边之后才会在到达的那
个点上休息。她想知道,是否存在一种连续的跳法,使得她有机会在所有
的树上都休息至少一次。
 对于这种跳法,你可以任选起点,允许重复经过边,允许重复经过点。
 但是超萌小松鼠是一只有梦想的小松鼠,她有时能够突破自己的极限,
使一些原本无法互相到达的两个点能够通过一次跳跃互相到达。
Input 
 第一行两个数n,m。n表示点的个数,m表示边的条数
 接下来m行,每行两个数xi,yi,表示xi和yi之间能够通过一次跳跃互相到
达。
 接下来一行一个数q,表示询问的个数。
 接下来q行,其中的第i行每行两个数ai,bi。表示在原图的基础上加上从ai到bi的
边。即成为一张n个点m + 1条边的图。
 保证给出的原图是个连通图,1 <= ai; bi; xi; yi <= n。
Output 
 输出一共q行,对于第i个询问,当在原图的基础上加上ai与bi间的无向边
后,如果小松鼠能够找到一种连续的跳法,使得她有机会在所有的树上至
少休息一次,输出一行“Yes”,否则输出一行“No”。(不包含引号)
Constraints 
 对于前50%,n; q <= 103 , m <= 2 103。
 对于100%,n; q <= 105, m <= 2 105。
3
StopAllSounds
10月3日,在杭州市西湖景区,一只小松鼠不停地接受一道道食物,花生、
玉米、饼干,可谓来者不拒,憨态可掬的模样吸引了众多围观者...
Description 
 小松鼠开心地在树之间跳跃着,突然她停了下来。因为眼前出现了一个
拿着专克超萌小松鼠的法宝————超萌游戏机的游客!
 超萌游戏机之所以拥有这个名字,是因为它的屏幕是一个n 2的矩形。
小松鼠接过游戏机,开始了她的第一个游戏:俄罗斯方块。
 考虑到小松鼠的智商,游戏机里的方块只有下面四种,方块按顺序下落,
图1: 俄罗斯方块的种类
可以在任意时刻(甚至是下落前)对其进行不限次数的旋转操作。
 由于四种方块最小宽度都为2,因此下落的时候在水平方向上是不能够移
动的。我们称当前方块下落的过程完成了,当且仅当其再往下移动一个单
位就会与之前覆盖的方块有部分相重叠。小松鼠想要知道,在这个n 2的
游戏界面中,一共会出现多少种游戏状态。游戏状态指单次方块下落的过
程完成后,不要求游戏结束(即不要求第1行非空),且界面中出现的必须
是完整的方块。
 两种游戏状态被认为是相同的,当且仅当游戏界面中的每一个格子两种
状态下被覆盖的方块类型都相同(或都不被覆盖)。
 如下图属于两种不同的游戏状态。
4
 再次考虑到小松鼠的智商,答案模10^9 + 7 输出。
Input 
 一行一个数n,表示游戏界面的长度。
Output 
 一个数,表示游戏界面的状态数在模10^9 + 7意义下的值。
Constraints 
 对于前10%,n <= 10。
 对于前30%,n <= 1000。
 对于前60%,n <= 100000。
 对于100%,n <= 1000000。
 人生不能失去信仰,数据有梯度。
一看就是乱dp,显然直接二维存会爆,所以第一维存左边的高度,第二维存右边相对左边的相对高度,显然只需要开5的大小,其他的稍微注意一下细节吧。

#include <cstdio>  
#include <cmath>  
#include <ctime>  
#include <string>  
#include <cstring>  
#include <cstdlib>  
#include <iostream>  
#include <algorithm>  
 
#define FOR(i,a,b) for((i)=(a);(i)<=(b);(i)++)  
#define FORP(i,a,b) for(int i=(a);i<=(b);i++)  
#define FORM(i,a,b) for(int i=(a);i>=(b);i--)  
#define maxn 1000005 
#define maxm 100005 
#define INF 1070000000  
using namespace std;  
typedef long long ll;  
typedef unsigned long long ull;  
  
template<class T> inline  
void read(T& num){  
    num = 0; bool f = true;char ch = getchar();  
    while(ch < '0' || ch > '9') { if(ch == '-') f = false;ch = getchar();}  
    while(ch >= '0' && ch <= '9') {num = num * 10 + ch - '0';ch = getchar();}  
    num = f ? num: -num;  
} 
int out[100]; 
template<class T> inline 
void write(T x,char ch){ 
	if (x==0) {putchar('0'); putchar(ch); return;} 
	if (x<0) {putchar('-'); x=-x;} 
	int num=0; 
	while (x){ out[num++]=(x%10); x=x/10;} 
	FORM(i,num-1,0) putchar(out[i]+'0'); putchar(ch); 
} 
/*==================split line==================*/ 
const double eps=1e-8; 
#define MOD 1000000007;
const int l[6] = {2, 1, 0, 0, 0};
const int r[6] = {0, 0, 0, 1, 2};
const int hl[6] = {3, 2, 2, 3, 3, 3};
const int hr[6] = {2, 3, 2, 2, 1, 3};
ll f[maxn][10];
int i, j;
int n;
ll ans = 0;
int ord(int t){ 
	switch(t){
		case 0: return 3;
		case 2: return 1;
		case 1: return 2;
		case -1: return 4;
		case -2: return 5;
	}
}
void updata(ll &x){ x += f[i][j], x %= MOD;}
int main(){
	read(n); 
	f[0][3] = 1;
	FOR(i, 0, n - 1) 
		FOR(j, 1, 5) 
		if (f[i][j]){
			if (j == 1 || j == 2){
				updata(f[i + 3][ord(1)]); updata(f[i + 2][ord(-1)]);
				updata(f[i + 2][ord(0)]); updata(f[i + 2][ord(1)]);
				updata(f[i + 3][ord(2)]); updata(f[i + j][ord(0)]);
			}
			if (j == 3) FORP(k, 0, 5)  updata(f[i + max(hl[k], hr[k])][ord(hl[k] - hr[k])]);
			if (j == 4 || j == 5) {
				updata(f[i + 2][ord(1)]); updata(f[i + 3][ord(-1)]);
				updata(f[i + 2][ord(0)]); updata(f[i + 3][ord(1)]);
				updata(f[i + 3][ord(2)]); updata(f[i + 3][ord(0)]);
			}
		}
	FOR(i, 0, n)
		FOR(j, 1, 5) ans += f[i][j], ans %= MOD;
	write(ans,'\n');
	return 0; 
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值