1. 程式人生 > >矩陣快速冪刷題系列

矩陣快速冪刷題系列

opened alt bit view multi long 快速 for each file

來源自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

矩陣快速冪刷題系列