hdu 2065(递推+矩阵乘法)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2065
思路:递推:
dp[len][0]表示长度为len的全部合法字符串的个数;
dp[len][1]表示长度为len的,仅有A出现奇数次的字符串的个数;
dp[len][2]表示长度为len的,仅有C出现奇数次的字符串的个数;
dp[len][3]表示长度为len的,A,C均出现奇数次的字符串的个数。
于是我们可以得到下列方程:
dp[len][0]=2*dp[len-1][0]+dp[len-1][1]+dp[len-1][2];
dp[len][1]=dp[len-1][0]+2*dp[len-1][1]+dp[len-1][3];
dp[len][2]=dp[len-1][0]+2*dp[len-1][2]+dp[len-1][3];
dp[len][3]=dp[len-1][1]+dp[len-1][2]+2*dp[len-1][3];
于是最终的解即为dp[len][0]。
然后就是求二分求幂了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 typedef long long LL; 7 struct Matrix{ 8 int map[4][4]; 9 }mat,U; 10 LL n; 11 12 void Initiate() 13 { 14 for(int i=0;i<4;i++) 15 for(int j=0;j<4;j++) 16 mat.map[i][j]=1; 17 for(int i=0;i<4;i++) 18 mat.map[i][3-i]=0; 19 for(int i=0;i<4;i++){ 20 mat.map[i][i]=2; 21 U.map[i][i]=1; 22 } 23 } 24 25 Matrix Mul(const Matrix &a,const Matrix &b) 26 { 27 Matrix c; 28 for(int i=0;i<4;i++){ 29 for(int j=0;j<4;j++){ 30 c.map[i][j]=0; 31 for(int k=0;k<4;k++){ 32 c.map[i][j]+=a.map[i][k]*b.map[k][j]; 33 } 34 c.map[i][j]%=100; 35 } 36 } 37 return c; 38 } 39 40 int Pow(LL n){ 41 Matrix p=mat,q=U; 42 while(n){ 43 if(n&1) 44 q=Mul(p,q); 45 n>>=1; 46 p=Mul(p,p); 47 } 48 return (q.map[0][0]*2+q.map[0][1]+q.map[0][2])%100; 49 } 50 51 int main() 52 { 53 int _case; 54 Initiate(); 55 while(scanf("%d",&_case),_case) 56 { 57 int t=1; 58 while(_case--){ 59 scanf("%I64d",&n); 60 printf("Case %d: %d\n",t++,Pow(n-1)); 61 } 62 puts(""); 63 } 64 return 0; 65 }