花园 洛谷p1357

来源:互联网 发布:软件开发资料填写 编辑:程序博客网 时间:2024/05/08 23:13

题目描述

小L有一座环形花园,沿花园的顺时针方向,他把各个花圃编号为1~N(2<=N<=10^15)。他的环形花园每天都会换一个新花样,但他的花园都不外乎一个规则,任意相邻M(2<=M<=5,M<=N)个花圃中有不超过K(1<=K<M)个C形的花圃,其余花圃均为P形的花圃。

例如,N=10,M=5,K=3。则

CCPCPPPPCC 是一种不符合规则的花圃;

CCPPPPCPCP 是一种符合规则的花圃。

请帮小L求出符合规则的花园种数Mod 1000000007

由于请您编写一个程序解决此题。

输入输出格式

输入格式:

一行,三个数N,M,K。

输出格式:

花园种数Mod 1000000007

输入输出样例

输入样例#1: 复制
【样例输入1】10 5 3【样例输入2】6 2 1
输出样例#1: 复制
【样例输出1】458【样例输出2】18

说明

【数据规模】

40%的数据中,N<=20;

60%的数据中,M=2;

80%的数据中,N<=10^5。

100%的数据中,N<=10^15。


前80%的N<=100000N<=100000,还是可做的,和容易想到用DP搞,因为m<=5m<=5,,所以我们可以把最后的m盆花进行状压,f[i][j]f[i][j]表示共有i盆花且最后mm盆花的状态为jj的时候的方案数,那么我们就可以将以个可以转移给jj的状态的方案书加给他,即状态转移方程为f[i][j] = Σ{f[i-1][k]}f[i][j]=Σf[i1][k],那么问题又来了,题目中说所有的花都是环形,我这样做如何保证所有的方案都是环形的呢.我们可以多次DP

每次DP前将其中一个合法状态赋值kk为1,然后从mm盆花一直更新到m+nm+n盆花,最后我再将f[m+n][k]f[m+n][k]加到ansans中,这样我就可以保证最后更新出的答案中的方案数都是有最开始的kk开始且又以kk结束的方案,即组成了一个环.最后的ansans即为我的方案数.

其实我们会发现,对于一个合法状态,更新它的合法状态始终是不变的,并且总会更新N次,也就是说对于每一次转移,都相当于给原数组乘以了一个矩阵,并且很显然这个矩阵是不变的,而且它就是当初我们处理出来的表示转移关系的那个bool数组,既然这样,那我们的$f[i][j]中的第一维就没有任何意义了,我们可以将它扔掉,变成一个一维数组,然后我们又会发现,其实最终的答案就是那个矩阵的对角线之和。

80分:

#include<iostream>#include<cstring>#define f(i,l,r) for(i=(l);i<=(r);i++)using namespace std;const int MOD=1000000007;long long n;int m,K,S,sta[100],v[100][100];int f[100010][64],ans=0;inline Matrix Pow(Matrix x,int k){Matrix ans=x;k--;for(;k;k>>=1,x=x*x){if(k&1){ans=ans*x;}}return ans;}inline bool pd(int s){int i,num=0;f(i,0,m-1){if(s&(1<<i)) num++;if(num>K) return false;}return true;}inline bool check(int x,int y){int i;f(i,0,m-2){int a=(sta[x]>>i)&1;int b=(sta[y]>>i+1)&1;if(a!=b) return false;}return true;}inline void dp(int s){int i,j,k;memset(f,0,sizeof(f));f[m][s]=1;f(i,m+1,m+n){f(j,1,sta[0]){f(k,1,sta[0]){f[i][j]=(f[i][j]+f[i-1][k]*v[k][j])%MOD;}}}ans=(ans+f[m+n][s])%MOD;}int main(){ios::sync_with_stdio(false);int i,j;cin>>n>>m>>K;S=(1<<m)-1;f(i,0,S){int num=0;if(pd(i)) sta[++sta[0]]=i;}f(i,1,sta[0]){f(j,1,sta[0]){if(check(i,j)){A.v[i][j]=1;}}}f(i,1,sta[0]){dp(i);}cout<<ans<<endl;return 0;}

100分:

#include<iostream>#include<cstring>#define f(i,l,r) for(i=(l);i<=(r);i++)using namespace std;const int MOD=1000000007;long long n;int m,K,S,sta[100];int f[100010][64];long long ans=0;struct Matrix{long long v[50][50];Matrix(){memset(v,0,sizeof(v));}Matrix operator *(const Matrix& x)const{Matrix ans;int i,j,k;f(i,1,sta[0]){f(j,1,sta[0]){f(k,1,sta[0]){ans.v[i][j]=(ans.v[i][j]+v[i][k]*x.v[k][j])%MOD;}}}return ans;}}A;inline Matrix Pow(Matrix x,long long k){Matrix ans=x;k--;for(;k;k>>=1,x=x*x){if(k&1){ans=ans*x;}}return ans;}inline bool pd(int s){int i,num=0;f(i,0,m-1){if(s&(1<<i)) num++;if(num>K) return false;}return true;}inline bool check(int x,int y){int i;f(i,0,m-2){int a=(sta[x]>>i)&1;int b=(sta[y]>>i+1)&1;if(a!=b) return false;}return true;}int main(){ios::sync_with_stdio(false);int i,j;cin>>n>>m>>K;S=(1<<m)-1;f(i,0,S){int num=0;if(pd(i)) sta[++sta[0]]=i;}f(i,1,sta[0]){f(j,1,sta[0]){if(check(i,j)){A.v[i][j]=1;}}}Matrix b=Pow(A,n);f(i,1,sta[0]){ans=(ans+b.v[i][i])%MOD;}cout<<ans<<endl;return 0;}


原创粉丝点击