题目链接:https://vjudge.net/contest/333591#problem/L
题意:用m个字符构成长度为n的串,其中存在形如“ab”(表示a后不能放置b)的条件约束,问共有多少种构造方法。
思路:矩阵快速幂,建立一个数组num[53][53],num[i][j]=1表示i号字符的下一个字符可以是j号字符,num[i][j]=0表示i号字符下一个字符不能为j号字符,计算该矩阵的(n-1)次幂,再与模为sqrt(m)的m维向量相乘,算出所得向量的所有分量的和,即为答案。
反思:唯一的感想就是——矩阵快速幂太强大了!!!!!(上次用矩阵快速幂是那道计算斐波那契数列的题)
代码如下:
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 long long n; 5 const int mo=1e9+7; 6 int m,k; 7 long long num[60]; 8 long long restrict[60][60]; 9 char tm1,tm2; 10 11 int pow(long long x){ 12 x--; 13 long long res[60][60],ttp[60][60]={0}; 14 for(int i=1;i<=m;i++) 15 res[i][i]=1; 16 while(x!=0){ 17 if(x&1){ 18 memset(ttp,0,sizeof(ttp)); 19 for(int ii=1;ii<=m;ii++){ 20 for(int i=1;i<=m;i++){ 21 for(int j=1;j<=m;j++){ 22 ttp[ii][j]+=res[ii][i]*restrict[i][j]%mo; 23 ttp[ii][j]%=mo; 24 } 25 } 26 } 27 for(int i=1;i<=m;i++) 28 for(int j=1;j<=m;j++) 29 res[i][j]=ttp[i][j]; 30 } 31 x>>=1; 32 memset(ttp,0,sizeof(ttp)); 33 for(int ii=1;ii<=m;ii++){ 34 for(int i=1;i<=m;i++){ 35 for(int j=1;j<=m;j++){ 36 ttp[ii][j]+=restrict[ii][i]*restrict[i][j]%mo; 37 ttp[ii][j]%=mo; 38 } 39 } 40 } 41 for(int i=1;i<=m;i++) 42 for(int j=1;j<=m;j++) 43 restrict[i][j]=ttp[i][j]; 44 } 45 long long ans=0; 46 for(int i=1;i<=m;i++){ 47 for(int j=1;j<=m;j++){ 48 ans+=num[i]*res[i][j]%mo; 49 ans%=mo; 50 } 51 } 52 return ans; 53 } 54 int main(){ 55 scanf("%I64d%d%d",&n,&m,&k); 56 for(int i=1;i<=m;i++){ 57 for(int j=1;j<=m;j++) 58 restrict[i][j]=1; 59 num[i]=1; 60 } 61 for(int i=1;i<=k;i++){ 62 scanf("\n%c%c",&tm1,&tm2); 63 //printf("%c %c\n",tm1,tm2); 64 int x1=tm1>‘Z‘?tm1-‘a‘+1:tm1-‘A‘+27; 65 int x2=tm2>‘Z‘?tm2-‘a‘+1:tm2-‘A‘+27; 66 //printf("%d %d\n",x1,x2); 67 restrict[x1][x2]=0; 68 } 69 printf("%d",pow(n)); 70 return 0; 71 }
DecodingGenome(CodeForces-222E)【矩阵快速幂】
原文:https://www.cnblogs.com/xxmlala-fff/p/11664332.html