BZOJ(本校) 3048 染色 - dp&递推找规律
2016-03-07 17:43
288 查看
【问题描述】
最近大大很happy,她制作了一些小旗,小旗都排成一列。现在她有四种颜色,分别为R,B,W,Y。突发奇想的大大决定出个问题考考你。她想知道,n面小旗染色有多少种不同的方案数。这样太简单了,答案不就是4^n么。于是她加了点限制,有5个限制条件,分别要求
1、相邻两面旗染色不相同
2、R,B两种颜色不能相邻
3、Y,W两种颜色不能相邻
4、R,W,B不能在一起。即不能出现连续三个是RWB的排列。
5、正反一样的算一种
但是大大觉得这样还是太简单了,于是她定义f(n)为n面红旗的方案数,她给你L和R两个正整数,让你计算∑Ri=Lf(i)\sum_{i=L}^{R}{f(i)},但是由于答案太大,你只需要mod 1000000007即可。
求答案。
【输入格式】
共一行两个正整数L和R,保证L<=R。
【输出格式】
输出只有一行,一个整数。
【样例输入输出1】
3 4
///
23
对于样例一的解释:
3面小旗:BWB, BYB, BYR, RWR, RYR, WBW, WBY, WRW, WRY, YBY, YRY (11 种)。
4面小旗: BWBW, BWBY, BYBW, BYBY, BYRW, BYRY, RWRW, RWRY, RYBW, RYBY, RYRW, RYRY (12 种)。
所以答案为11+12=23种。
【样例输入输出2】
5 6
///
64
【数据范围】
对于10%的数据,有1<=L<=R<=10
另有40%的数据,有 R-L+1<=10
对于100%的数据,1<=L<=R <=1000000000
将dp值打个表,发现单从奇数位置或偶数位置看,竟然是等比数列!
那么耐着性子用等比求和公式推一推就出来了,具体看程序吧。
最近大大很happy,她制作了一些小旗,小旗都排成一列。现在她有四种颜色,分别为R,B,W,Y。突发奇想的大大决定出个问题考考你。她想知道,n面小旗染色有多少种不同的方案数。这样太简单了,答案不就是4^n么。于是她加了点限制,有5个限制条件,分别要求
1、相邻两面旗染色不相同
2、R,B两种颜色不能相邻
3、Y,W两种颜色不能相邻
4、R,W,B不能在一起。即不能出现连续三个是RWB的排列。
5、正反一样的算一种
但是大大觉得这样还是太简单了,于是她定义f(n)为n面红旗的方案数,她给你L和R两个正整数,让你计算∑Ri=Lf(i)\sum_{i=L}^{R}{f(i)},但是由于答案太大,你只需要mod 1000000007即可。
求答案。
【输入格式】
共一行两个正整数L和R,保证L<=R。
【输出格式】
输出只有一行,一个整数。
【样例输入输出1】
3 4
///
23
对于样例一的解释:
3面小旗:BWB, BYB, BYR, RWR, RYR, WBW, WBY, WRW, WRY, YBY, YRY (11 种)。
4面小旗: BWBW, BWBY, BYBW, BYBY, BYRW, BYRY, RWRW, RWRY, RYBW, RYBY, RYRW, RYRY (12 种)。
所以答案为11+12=23种。
【样例输入输出2】
5 6
///
64
【数据范围】
对于10%的数据,有1<=L<=R<=10
另有40%的数据,有 R-L+1<=10
对于100%的数据,1<=L<=R <=1000000000
分析:
先写个满足1-4条件的dp,如果长度为偶数,一定满足条件5(相邻两个不能相等),f(len)=dp(len)/2;如果长度为奇数,f(len)=(dp(len)-dp(len/2+1))/2+dp(len/2+1) ,因为本身回文的只出现了一次,所以要再加上本身回文的。将dp值打个表,发现单从奇数位置或偶数位置看,竟然是等比数列!
那么耐着性子用等比求和公式推一推就出来了,具体看程序吧。
#include<cstdio> #include<algorithm> using namespace std; #define Mod 1000000007 int phi; void exgcd(int a,int b,int &d,int &x,int &y) { if(!b){ d=a; x=1,y=0; return ; } exgcd(b,a%b,d,y,x); y=1LL*y-(a/b)*x; } int Inv(int a,int b) { int d,x,y; exgcd(a,b,d,x,y); return (1LL*x%Mod+Mod)%Mod; } int mypow(int x,int k) { int ret=1; x%=Mod; while(k){ if(k&1) ret=1LL*ret*x%Mod; x=1LL*x*x%Mod; k>>=1; } return ret; } int sigma_pw(int q) { int r=mypow(3,q+1)%Mod; return ((1LL*r-1+Mod)%Mod*phi)%Mod; } int Line(int t) { int p=t,q=t-1; if(t%2) swap(p,q); return (1LL*8*(sigma_pw(p/2-1)%Mod)%Mod+1LL*14*(sigma_pw(q/2-1)%Mod)%Mod)%Mod; } int Getans(int n) { if(n==0) return 0; if(n==1) return 4; int p1=Line(n)%Mod,p2=Line(n%2==0?n/2:(n/2+1))%Mod; return ((((1LL*(p1-p2)%Mod+Mod)%Mod*phi)%Mod+p2)%Mod+(n>=1?1:0)*4)%Mod; } int main() { int L,R; scanf("%d%d",&L,&R); phi=Inv(2,Mod)%Mod; int p=Getans(R),q=Getans(L-1); printf("%d\n",(int)((1LL*(p-q)%Mod+Mod)%Mod)); }
相关文章推荐
- 树--天平问题
- nginx安装
- lintcode-easy-Trailing Zeros
- javascript 获得上个月、获取下个月日期
- PHP汉字转拼音
- leetcode:Flatten Binary Tree to Linked List
- Layout
- 使用GUI工具高效构建你自己的Nuget包
- 多线程编程--- __thread关键字
- cocos2d-x开发的《派对小游戏》-github源码分享
- 【KMP模板】POJ3461-Oulipo
- JDK安装和配置
- java用三种方法实现阶乘n!
- Android Studio使用
- bananapi之BPI-D1镜像烧录
- C语言-基础
- Java学习心得
- DECIMAL Data Type Characteristics
- Java之Base64实现文件和字符串之间的转换
- 图片延迟加载技术