矩阵快速幂刷题系列

来源自http://blog.csdn.net/chenguolinblog/article/details/10309423

hdu 1575

Tr A

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5587    Accepted Submission(s): 4200


Problem Description
A为一个方阵,则Tr A表示A的迹(就是主对角线上各项的和),现要求Tr(A^k)%9973。
 

 

Input
数据的第一行是一个T,表示有T组数据。
每组数据的第一行有n(2 <= n <= 10)和k(2 <= k < 10^9)两个数据。接下来有n行,每行有n个数据,每个数据的范围是[0,9],表示方阵A的内容。
 

 

Output
对应每组数据,输出Tr(A^k)%9973。
 

 

Sample Input
2 2 2 1 0 0 1 3 99999999 1 2 3 4 5 6 7 8 9
 

 

Sample Output
2 2686

 

裸矩阵快速幂。

 1 #include<bits/stdc++.h>
 2 #define clr(x) memset(x,0,sizeof(x))
 3 #define LL long long
 4 #define mod 9973
 5 using namespace std;
 6 typedef vector<LL> vec;
 7 typedef vector<vec> mat;
 8 mat mul(const mat &a,const mat &b)
 9 {
10     int row=a.size();
11     int col=b[0].size();
12     int mid=b.size();
13     mat c(row,vec(col));
14     for(int i=0;i<row;i++)
15         for(int j=0;j<col;j++)
16             for(int k=0;k<mid;k++)
17                 c[i][j]=(c[i][j]+a[i][k]*b[k][j]%mod)%mod;
18     return c;
19 }
20 mat quick_pow(mat a,LL n)
21 {
22     int len=a.size();
23     mat res(len,vec(len));
24     for(int i=0;i<len;i++)
25         res[i][i]=1;
26     while(n)
27     {
28         if(n&1)
29             res=mul(res,a);
30         a=mul(a,a);
31         n>>=1;
32     }
33     return res;
34 }
35 int main()
36 {
37     int T,n;
38     LL k,ansed;
39     scanf("%d",&T);
40     while(T--)
41     {
42         scanf("%d%lld",&n,&k);
43         mat ans(n,vec(n));
44         for(int i=0;i<n;i++)
45             for(int j=0;j<n;j++)
46                 scanf("%lld",&ans[i][j]);
47         ans=quick_pow(ans,k);
48         ansed=0;
49         for(int i=0;i<n;i++)
50             ansed=(ans[i][i]+ansed)%mod;
51         printf("%lld\n",ansed);
52     }
53     return 0;
54 }
View Code

 

 

hdu 1757

A Simple Math Problem

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5264    Accepted Submission(s): 3200


Problem Description
Lele now is thinking about a simple function f(x).

If x < 10 f(x) = x.
If x >= 10 f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10);
And ai(0<=i<=9) can only be 0 or 1 .

Now, I will give a0 ~ a9 and two positive integers k and m ,and could you help Lele to caculate f(k)%m.
 

 

Input
The problem contains mutiple test cases.Please process to the end of file.
In each case, there will be two lines.
In the first line , there are two positive integers k and m. ( k<2*10^9 , m < 10^5 )
In the second line , there are ten integers represent a0 ~ a9.
 

 

Output
For each case, output f(k) % m in one line.
 

 

Sample Input
10 9999 1 1 1 1 1 1 1 1 1 1 20 500 1 0 1 0 1 0 1 0 1 0
 

 

Sample Output
45 104
 

裸矩阵快速幂。

 1 #include<bits/stdc++.h>
 2 #define clr(x) memset(x,0,sizeof(x))
 3 #define LL long long
 4 using namespace std;
 5 typedef vector<LL> vec;
 6 typedef vector<vec> mat;
 7 int a[20];
 8 LL m,k,p,n;
 9 mat mul(const mat &a,const mat &b,LL mod)
10 {
11     mat c(a.size(),vec(b[0].size()));
12     for(int i=0;i<a.size();i++)
13         for(int j=0;j<b[0].size();j++)
14             for(int k=0;k<b.size();k++)
15             {
16                 c[i][j]=(c[i][j]%mod+a[i][k]*b[k][j]%mod)%mod;
17             }
18     return c;
19 }
20 mat quick_pow(mat a,LL n,LL mod)
21 {
22     int sized=a.size();
23     mat res(sized,vec(sized));
24     for(int i=0;i<10;i++)
25         res[i][i]=1;
26     while(n)
27     {
28         if(n&1)
29         {
30             res=mul(res,a,mod);
31         }
32         n>>=1;
33         a=mul(a,a,mod);
34     }
35     return res;
36 }
37 int main()
38 {
39     while(scanf("%lld%lld",&n,&m)!=EOF)
40     {
41         for(int i=0;i<10;i++)
42             scanf("%lld",&a[i]);
43         if(n<10)
44         {
45             printf("%lld\n",n%m);
46             continue;
47         }
48         mat multi(10,vec(10));
49         mat ans(1,vec(10));
50         for(int i=0;i<10;i++)
51         {
52             ans[0][i]=i;
53             multi[i][9]=a[9-i];
54         }
55         for(int i=0;i<9;i++)
56             multi[i+1][i]=1;
57         multi=quick_pow(multi,n-9,m);
58         ans=mul(ans,multi,m);
59         printf("%lld\n",ans[0][9]);
60     }
61     return 0;
62 }
View Code

 

2017广西邀请赛D题

Covering

Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 0    Accepted Submission(s): 0


Problem Description
Bob's school has a big playground, boys and girls always play games here after school.

To protect boys and girls from getting hurt when playing happily on the playground, rich boy Bob decided to cover the playground using his carpets.

Meanwhile, Bob is a mean boy, so he acquired that his carpets can not overlap one cell twice or more.

He has infinite carpets with sizes of 1×2 and 2×1 , and the size of the playground is 4×n .

Can you tell Bob the total number of schemes where the carpets can cover the playground completely without overlapping?
 

 

Input
There are no more than 5000 test cases.

Each test case only contains one positive integer n in a line.

1n1018
 

 

Output
For each test cases, output the answer mod 1000000007 in a line.
 

 

Sample Input
1 2
 

 

Sample Output
1 5

我们从连通性考虑该题。4*i的地板最右端有最多16个状态,将状态压缩后就是0~15这几个数。而4*i可由4*(i-1)的16个状态得出。我们将其状态转移用矩阵表示,于是可以用矩阵相乘得到最终状态。并且我们需要的是0状态。由于n过大,需要使用矩阵快速幂。然而16*16*16的矩阵相乘时间复杂度过高,我们把无用状态剔除后剩余6个状态,这样就不会T了。
  1 #include<bits/stdc++.h>
  2 #define clr(x) memset(x,0,sizeof(x))
  3 #define LL long long
  4 #define mod 1000000007
  5 using namespace std;
  6 typedef vector<LL> vec;
  7 typedef vector<vec> mat;
  8 LL n,m;
  9 mat mart(6,vec(6)),martp(16,vec(16)),martpp(6,vec(6)),foc(6,vec(6)),res(6,vec(6));
 10 mat ori(1,vec(6)),oripp(1,vec(6));
 11 int code1[10],code2[10],code3[10];
 12 int pos[6]={0,3,6,9,12,15};
 13 void decode(int p,int *code)
 14 {
 15     for(int i=0;i<4;i++)
 16     {
 17         code[i]=p&1;
 18         p>>=1;
 19     }
 20     return ;
 21 }
 22 void init()
 23 {
 24     oripp[0][0]=1;
 25     bool flag;
 26     for(int i=0;i<16;i++)
 27     {
 28         decode(i,code1);
 29         for(int j=0;j<16;j++)
 30         {
 31             flag=0;
 32             decode(j,code2);
 33             clr(code3);
 34             for(int k=0;k<4;k++)
 35             {
 36                 if(code2[k]==1)
 37                     if(code1[k]==1)
 38                     {
 39                         flag=1;
 40                         break;
 41                     }
 42                 if(code2[k]==0 && code1[k]==0 && code3[k]==0)
 43                 {
 44                     if(k<3 && code2[k+1]==0 && code1[k+1]==0)
 45                     {
 46                         code3[k+1]=code3[k]=1;
 47                     }
 48                     else
 49                     {
 50                         flag=1;
 51                         break;
 52                     }
 53                 }
 54             }
 55             if(flag==0)
 56                 martp[j][i]=1;
 57         }
 58     }
 59     for(int i=0;i<6;i++)
 60         for(int j=0;j<6;j++)
 61     {
 62         martpp[i][j]=martp[pos[i]][pos[j]];
 63     }
 64     return ;
 65 }
 66 void mul(mat &a,mat &b,mat &c)
 67 {
 68     int row=a.size(),col=b[0].size(),mid=b.size();
 69     for(int i=0;i<row;i++)
 70         for(int j=0;j<col;j++)
 71         {
 72             c[i][j]=0;
 73             for(int k=0;k<mid;k++)
 74             {
 75                 c[i][j]=(c[i][j]+a[i][k]*b[k][j]%mod)%mod;
 76             }
 77         }
 78     for(int i=0;i<row;i++)
 79         for(int j=0;j<col;j++)
 80         {
 81             a[i][j]=c[i][j];
 82         }
 83     return ;
 84 }
 85 void quick_pow(mat &multi,LL n,mat &res)
 86 {
 87     int row=multi.size();
 88     for(int i=0;i<row;i++)
 89     {
 90         res[i][i]=1;
 91         for(int j=0;j<row;j++)
 92             if(i!=j)
 93              res[i][j]=0;
 94     }
 95     while(n)
 96     {
 97         if(n&1)
 98         {
 99             mul(res,multi,foc);
100         }
101         mul(multi,multi,foc);
102         n>>=1;
103     }
104     for(int i=0;i<row;i++)
105         for(int j=0;j<row;j++)
106             multi[i][j]=res[i][j];
107     return;
108 }
109 int main()
110 {
111     init();
112     while(scanf("%I64d",&n)!=EOF)
113     {
114         ori=oripp;
115         mart=martpp;
116         quick_pow(mart,n,res);
117         mul(ori,mart,foc);
118         printf("%I64d\n",ori[0][0]);
119     }
120     return 0;
121 }
View Code

 

hdu 2604

Queuing

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6110    Accepted Submission(s): 2661


Problem Description
Queues and Priority Queues are data structures which are known to most computer scientists. The Queue occurs often in our daily life. There are many people lined up at the lunch time. 

  Now we define that ‘f’ is short for female and ‘m’ is short for male. If the queue’s length is L, then there are 2L numbers of queues. For example, if L = 2, then they are ff, mm, fm, mf . If there exists a subqueue as fmf or fff, we call it O-queue else it is a E-queue.
Your task is to calculate the number of E-queues mod M with length L by writing a program.
 

 

Input
Input a length L (0 <= L <= 10 6) and M.
 

 

Output
Output K mod M(1 <= M <= 30) where K is the number of E-queues with length L.
 

 

Sample Input
3 8 4 7 4 8
 

 

Sample Output
6 2 1

 


本题存在四种队列结尾的状态,分别是以ff,fm,mf,mm为结尾。对于题目要求的E队列,那么只要长度为n的队列结尾加上某个字母不形成fff和fmf,那么就可以转移为长度为n+1的对应队列。对四个结尾手推下转移矩阵,然后做矩阵快速幂就行了。长度为0的队列对应ff,fm,mf,mm为结尾的初始序列为(0,0,0,1),由长度为2的队列的序列依照转移矩阵可以逆推得到。
 1 #include<bits/stdc++.h>
 2 #define clr(x) memset(x,0,sizeof(x))
 3 #define clr_1(x) memset(x,-1,sizeof(x))
 4 #define LL long long 
 5 #define mod 1000000007
 6 using namespace std;
 7 typedef vector<LL> vec;
 8 typedef vector<vec> mat;
 9 mat ori(1,vec(4)),orip(1,vec(4)),mart(4,vec(4)),martp(4,vec(4));
10 void init()
11 {
12     orip[0][3]=1;
13     martp[0][1]=1;
14     martp[1][3]=1;
15     martp[2][0]=1;
16     martp[2][1]=1;
17     martp[3][2]=1;
18     martp[3][3]=1;
19     return ;
20 }
21 mat mul(const mat &a,const mat &b,const int &m)
22 {
23     int row=a.size(),col=b[0].size(),mid=b.size();
24     mat c(row,vec(col));
25     for(int i=0;i<row;i++)
26         for(int j=0;j<col;j++)
27          for(int k=0;k<mid;k++)
28          {
29              c[i][j]=(c[i][j]+a[i][k]*b[k][j]%m)%m;
30          }
31     return c;
32 }
33 mat quick_pow(mat multi,int n,const int &m)
34 {
35     int row=multi.size();
36     mat res(row,vec(row));
37     for(int i=0;i<row;i++)
38         res[i][i]=1;
39     while(n)
40     {
41         if(n&1)
42         {
43             res=mul(res,multi,m);
44         }
45         n>>=1;
46         multi=mul(multi,multi,m);
47     }
48     return res;
49 }
50 int m,n,ans;
51 int main()
52 {
53     init();
54     while(scanf("%d%d",&n,&m)!=EOF)
55     {
56         ori=orip;
57         mart=martp;
58         mart=quick_pow(mart,n,m);
59         ori=mul(ori,mart,m);
60         ans=0;
61         for(int i=0;i<4;i++)
62         {
63 //            printf("%d ",ori[0][i]);
64             ans+=ori[0][i];
65           }
66 //        printf("\n");
67         printf("%d\n",ans%m);
68     }
69     return 0;
70  } 
View Code

 

posted @ 2017-08-28 03:03  hk_lin  阅读(1157)  评论(0编辑  收藏  举报