题意:f代表男,m代表女,给定长度L,有2^L个不同组合的字符串(f、m相间),不能出现fmf和fff,问有几种组合。
思路:只要能找到递推公式就可以马上切掉这题。
设f(n)为字符串长度为n时复合条件的字符串个数,以字符串最后一个字符为分界点,当最后一个字符为m时前n-1个字符没有限制,即为f(n-1);当最后一个字符为f时就必须去除最后3个字符是fmf和fff的情况,在考虑最后两个字符为mf和ff的情况,显然不行;最后3个字符为fmf、mmf和fff、mff时只有当最后3个字符为mmf时前n-3个字符没有限制,即为f(n-3),当为mff时第n-3个字符可能为f因而对前n-3个字符串有限制;最后4个字符为fmff和mmff时mmff可行。这样就讨论完了字符串的构成情况,得出结论:
f(n)=f(n-1)+f(n-3)+f(n-4)
然后就像fibonacci那样构建矩阵用快速幂取模。。。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2604
View Code
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <string> 5 #include <algorithm> 6 #include <iostream> 7 using namespace std; 8 9 int f[5]={0,2,4,6,9}; 10 typedef struct In{ 11 int m[5][5]; 12 }Matrix; 13 Matrix init,unit,F; 14 int n,m; 15 16 void Init(){ 17 for(int i=1;i<=4;i++){ 18 for(int j=1;j<=4;j++){ 19 if(i==1&&j==1) init.m[i][j]=1; 20 else if(i==1&&j==3) init.m[i][j]=1; 21 else if(i==1&&j==4) init.m[i][j]=1; 22 else if(i==2&&j==1) init.m[i][j]=1; 23 else if(i==3&&j==2) init.m[i][j]=1; 24 else if(i==4&&j==3) init.m[i][j]=1; 25 else init.m[i][j]=0; 26 unit.m[i][j]=(i==j); 27 F.m[i][j]=0; 28 } 29 } 30 F.m[1][1]=f[4]; 31 F.m[2][1]=f[3]; 32 F.m[3][1]=f[2]; 33 F.m[4][1]=f[1]; 34 } 35 36 Matrix Mul(Matrix a,Matrix b){ 37 Matrix c; 38 for(int i=1;i<=4;i++) 39 for(int j=1;j<=4;j++){ 40 c.m[i][j]=0; 41 for(int k=1;k<=4;k++){ 42 c.m[i][j]+=a.m[i][k]*b.m[k][j]%m; 43 c.m[i][j]%=m; 44 } 45 } 46 return c; 47 } 48 49 Matrix Pow(Matrix a,Matrix b){ 50 while(n){ 51 if(n&1) b=Mul(a,b); 52 a=Mul(a,a); 53 n>>=1; 54 } 55 return b; 56 } 57 58 int main(){ 59 60 // freopen("data.in","r",stdin); 61 // freopen("data.out","w",stdout); 62 63 while(scanf("%d%d",&n,&m)!=EOF){ 64 if(n<5){ 65 printf("%d\n",f[n]%m); 66 continue; 67 } 68 Init(); 69 n-=4; 70 Matrix x=Pow(init,unit); 71 x=Mul(x,F); 72 printf("%d\n",x.m[1][1]%m); 73 } 74 return 0; 75 }