wenbao与矩阵

 

矩阵满足分配率和结合律(非常重要)

****但是不满足交换律

 

循环矩阵:

  两个循环矩阵乘积依然是循环矩阵

 

矩阵乘法

 

 1 struct mat{
 2     int n, m;
 3     double data[MAXN][MAXN];
 4 };
 5 
 6 int mul(mat& c, const mat& a, const mat& b){
 7     int i, j, k;
 8     if (a.m != b.n)
 9         return 0;
10     c.n = a.n;
11     c.m = b.m;
12     for (i = 0; i < c.n; i++)
13         for (j = 0; j < c.m; j++)
14             for (c.data[i][j] = k = 0; k < a.m; k++)
15                 c.data[i][j] += a.data[i][k] * b.data[k][j];
16     return 1;
17 }

 

 

矩阵快速幂

 

 1 struct Node{
 2     ll x[16][16];
 3 };
 4 Node mul(Node xx, Node yy){
 5     Node X;
 6     for(int i = 0; i < d; ++i){
 7         for(int j = 0; j < d; ++j){
 8             X.x[i][j] = 0;
 9             for(int k = 0; k < d; ++k){
10                 X.x[i][j] = (X.x[i][j] + (xx.x[i][k]*yy.x[k][j])%m) % m;
11             }
12         }
13     }
14     return X;
15 }
16 Node q_m(Node A, ll x){
17     Node AAA;
18     for(int i = 0; i < d; ++i){
19         for(int j = 0; j < d; ++j){
20             AAA.x[i][j] = (i == j);
21             //printf("%lld ", AAA.x[i][j]);
22         }
23         //puts("");
24     }
25     while(x){
26         if(x&1) AAA = mul(AAA, A);
27         A = mul(A, A);
28         x >>= 1;
29     }
30     return AAA;
31 }

 

--------------------------------------------------------------------------------------------------------------------

 

矩阵快速幂入门题一:

 

http://acm.hdu.edu.cn/showproblem.php?pid=1575

 

直接求矩阵快速幂

 

 1 #include <iostream>
 2 using namespace std;
 3 #define ll long long
 4 const ll Mod = 9973;
 5 int n;
 6 ll k;
 7 struct Node{
 8     ll x[11][11];
 9 }A;
10 Node mul(Node a, Node b){
11     Node AAA;
12     for(int i = 0; i < n; ++i){
13         for(int j = 0; j < n; ++j){
14             AAA.x[i][j] = 0;
15             for(int k = 0; k < n; ++k){
16                 AAA.x[i][j] = (AAA.x[i][j] + a.x[i][k]*b.x[k][j]%Mod)%Mod;
17             }
18         }
19     }
20     return AAA;
21 }
22 ll q_m(){
23     Node AA;
24     for(int i = 0; i < n; ++i){
25         for(int j = 0; j < n; ++j){
26             AA.x[i][j] = (i == j);
27         }
28     }
29     while(k){
30         if(k&1) AA = mul(AA, A);
31         A = mul(A, A);
32         k >>= 1;
33     }
34     ll sum = 0;
35     for(int i = 0; i < n; ++i){
36         sum = (sum+AA.x[i][i])%Mod;
37     }
38     return sum;
39 }
40 int main(){
41     int t;
42     scanf("%d", &t);
43     while(t--){
44         scanf("%d%lld", &n, &k);
45         for(int i = 0; i < n; ++i){
46             for(int j = 0; j < n; ++j){
47                 scanf("%lld", &A.x[i][j]);
48             }
49         }
50         cout<<q_m()<<endl;
51     }
52     return 0;
53 }

 

--------------------------------------------------------------------------------------------------------------------

 

矩阵快速幂入门二:

 

http://codeforces.com/contest/185/problem/A

 

 

递推上三角形的个数。。。。。。。。。

其实直接推也可以的

 

 

 1 #include <iostream>
 2 using namespace std;
 3 #define ll long long 
 4 const ll Mod = 1e9+7;
 5 ll n;
 6 struct Node{
 7     ll x[2][2];
 8 };
 9 Node mul(Node a, Node b){
10     Node AAA;
11     for(int i = 0; i < 2; ++i){
12         for(int j = 0; j < 2; ++j){
13             AAA.x[i][j] = 0;
14             for(int k = 0; k < 2; ++k){
15                 AAA.x[i][j] = (AAA.x[i][j] + a.x[i][k]*b.x[k][j]%Mod)%Mod;
16             }
17         }
18     }
19     return AAA;
20 }
21 ll q_m(ll x){
22     Node AA, A;
23     A.x[0][0] = A.x[1][1] = 3LL;
24     A.x[0][1] = A.x[1][0] = 1LL;
25     AA.x[0][0] = AA.x[1][1] = 1LL;
26     AA.x[0][1] = AA.x[1][0] = 0LL;
27     while(x){
28         if(x&1) AA = mul(AA, A);
29         A = mul(A, A);
30         x >>= 1;
31     }
32     return AA.x[0][0];
33 }
34 int main(){
35     cin >> n;
36     cout<<q_m(n)<<endl;
37     return 0;
38 }

 

 

 1 #include <iostream>
 2 using namespace std;
 3 #define ll long long 
 4 const ll Mod = 1e9+7;
 5 ll n;
 6 ll q_m(ll x){
 7     ll xx = 1LL, xxx = 2LL;
 8     while(x){
 9         if(x&1) xx = xx*xxx%Mod;
10         xxx = xxx*xxx%Mod;
11         x >>= 1;
12     }
13     return xx;
14 }
15 int main(){
16     cin >> n;
17     if(n == 0){
18         cout<<1<<endl;
19         return 0;
20     }
21     cout<<(q_m(n-1LL)+q_m(2LL*n-1LL))%Mod<<endl;
22     return 0;
23 }

 

 

--------------------------------------------------------------------------------------------------------------------

矩阵快速幂入门三:

 

http://acm.hdu.edu.cn/showproblem.php?pid=2157

 

矩阵基本知识关于通路

 

 1 #include <iostream>
 2 #include <string.h>
 3 using namespace std;
 4 const int Mod = 1000;
 5 int n, m;
 6 struct Node{
 7     int x[22][22];
 8 }A;
 9 Node mul(Node a, Node b){
10     Node AAA;
11     for(int i = 0; i < n; ++i){
12         for(int j = 0; j < n; ++j){
13             AAA.x[i][j] = 0;
14             for(int k = 0; k < n; ++k){
15                 AAA.x[i][j] = (AAA.x[i][j] + a.x[i][k]*b.x[k][j]%Mod)%Mod;
16             }
17         }
18     }
19     return AAA;
20 }
21 void q_m(Node A, int xx, int yy, int zz){
22     Node AA;
23     for(int i = 0; i < n; ++i){
24         for(int j = 0; j < n; ++j){
25             AA.x[i][j] = (i == j);
26         }
27     }
28     while(zz){
29         if(zz&1) AA = mul(AA, A);
30         A = mul(A, A);
31         zz >>= 1;
32     }
33     /*
34     for(int i = 0; i < n; ++i){
35         for(int j = 0; j < n; ++j){
36             printf("%d ", AA.x[i][j]);
37         }
38         cout<<endl;
39     }
40     */
41     printf("%d\n", AA.x[xx][yy]);
42 }
43 int main(){
44     while(scanf("%d%d", &n, &m) == 2 && n+m){
45         memset(A.x, 0, sizeof(A.x));
46         while(m--){
47             int xx, yy;
48             scanf("%d%d", &xx, &yy);
49             A.x[xx][yy] = 1;
50         }
51         int t;
52         scanf("%d", &t);
53         while(t--){
54             int xx, yy, zz;
55             scanf("%d%d%d", &xx, &yy, &zz);
56             q_m(A, xx, yy, zz);
57         }
58     }
59     return 0;
60 }

 

--------------------------------------------------------------------------------------------------------------------

 

矩阵快速幂入门四

 

http://poj.org/problem?id=3070

 

 

求斐波那契数列

 

 

 1 #include <iostream>
 2 #include <stdio.h>
 3 using namespace std;
 4 #define ll long long
 5 const int Mod = 10000;
 6 struct Node{
 7     ll x[2][2];
 8 };
 9 Node mul(Node a, Node b){
10     Node AAA;
11     for(int i = 0; i < 2; ++i){
12         for(int j = 0; j < 2; ++j){
13             AAA.x[i][j] = 0;
14             for(int k = 0; k < 2; ++k){
15                 AAA.x[i][j] = (AAA.x[i][j] + a.x[i][k]*b.x[k][j]%Mod)%Mod;
16             }
17         }
18     }
19     return AAA;
20 }
21 void q_m(ll x){
22     Node AA, A;
23     for(int i = 0; i < 2; ++i){
24         for(int j = 0; j < 2; ++j){
25             AA.x[i][j] = (i == j);
26         }
27     }
28     A.x[0][0] = A.x[0][1] = A.x[1][0] = 1LL, A.x[1][1] = 0;
29     while(x){
30         if(x&1) AA = mul(AA, A);
31         A = mul(A, A);
32         x >>= 1;
33     }
34     /*
35     for(int i = 0; i < 2; ++i){
36         for(int j = 0; j < 2; ++j){
37             printf("%lld ", AA.x[i][j]);
38         }
39         cout<<endl;
40     }
41     */
42     printf("%lld\n", AA.x[0][1]);
43 }
44 int main(){
45     int n;
46     while(scanf("%lld", &n) && n != -1){
47         q_m(n);
48     }
49     return 0;
50 }

 

 

 

--------------------------------------------------------------------------------------------------------------------

 

大牛博客(关于递推构造矩阵)强烈推荐

 

 http://www.cnblogs.com/frog112111/archive/2013/05/19/3087648.html

 

--------------------------------------------------------------------------------------------------------------------

 

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=20&problem=1811&mosmsg=Submission+received+with+ID+18912945

 

  引用博客  http://blog.csdn.net/u010304217/article/details/39212049

 f[n]=a1*f[n-1]+a2*f[n-2]+...+ad*f[n-d];
    由于n太大,不能直接递推,需要用矩阵快速幂来解决,时间复杂度为O(d^3logn)
    举例,d=5的矩阵关系式为:
                |a1 a2 a3 a4 a5|                 | f[n]     |      | f[n+1] |  
                |1                      |                 | f[n-1]  |      | f[n]    |  
                |     1                 |  *              | f[n-2]  | =   | f[n-1] | (空白处为0)
                |          1            |                 | f[n-3]  |      | f[n-2] |
                |              1        |                 | f[n-4]  |      | f[n-3] |

 

矩阵快速幂 

 

 1 #include <iostream>
 2 #include <string.h>
 3 using namespace std;
 4 #define ll long long
 5 ll d, n, m, a[16], f[16];
 6 struct Node{
 7     ll x[16][16];
 8 };
 9 Node mul(Node xx, Node yy){
10     Node X;
11     for(int i = 0; i < d; ++i){
12         for(int j = 0; j < d; ++j){
13             X.x[i][j] = 0;
14             for(int k = 0; k < d; ++k){
15                 X.x[i][j] = (X.x[i][j] + (xx.x[i][k]*yy.x[k][j])%m) % m;
16             }
17         }
18     }
19     return X;
20 }
21 Node q_m(Node A, ll x){
22     Node AAA;
23     for(int i = 0; i < d; ++i){
24         for(int j = 0; j < d; ++j){
25             AAA.x[i][j] = (i == j);
26             //printf("%lld ", AAA.x[i][j]);
27         }
28         //puts("");
29     }
30     while(x){
31         if(x&1) AAA = mul(AAA, A);
32         A = mul(A, A);
33         x >>= 1;
34     }
35     return AAA;
36 }
37 int main(){
38     while(scanf("%lld%lld%lld", &d, &n, &m) && d+n+m){
39         ll xx;
40         for(int i = 0; i < d; ++i) scanf("%lld", &xx), a[i] = xx%m;
41         for(int i = 0; i < d; ++i) scanf("%lld", &xx), f[i] = xx%m;
42         if(n <= d){
43             printf("%lld\n", f[n-1]);
44             continue;
45         }
46         Node A;
47         for(int i = 0; i < d; ++i){
48             for(int j = 0; j < d; ++j){
49                 if(i == 0) A.x[i][j] = a[j];
50                 else A.x[i][j] = (i-1 == j);
51                 //printf("%lld ", A.x[i][j]);
52             }
53             //puts("");
54         }
55         Node AA = q_m(A, n-d);
56         ll sum = 0;
57         for(int i = 0; i < d; ++i){
58             sum = (sum + (AA.x[0][i]*f[d-i -1])%m) % m;
59         }
60         printf("%lld\n", sum);
61     }
62     return 0;
63 }

 

 

--------------------------------------------------------------------------------------------------------------------

 

 

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=20&problem=1705&mosmsg=Submission+received+with+ID+2137361

细胞自动机 

 

循环矩阵性质:循环矩阵相乘依然是循环矩阵,且该循环矩阵是对称的。。。。。。。。。

所以可以将  n^3log(k)  降为  n^2long(k)  因为只要算一行就可以了

 

做完这个题有个心得,,就是可以将矩阵的下标作为参数传来传去效率高,空间消耗小。。。。。。。牛X

 

 

 1 #include <iostream>
 2 #include <stdio.h>
 3 using namespace std;
 4 #define ll long long
 5 ll m[200][550], a[550];
 6 int num, n, d, mod, k;
 7 int mul(int x, int y){
 8     num++;
 9     for(int i = 0; i < n; ++i){
10         ll sum = 0;
11         for(int j = 0; j < n; ++j){
12             sum = (sum + m[x][j] * m[y][(n+j-i)%n] % mod) % mod;
13         }
14         m[num][i] = sum;
15     }
16     return num;
17 }
18 int q_m(int x){
19     int a = 0, b = 1;
20     while(x){
21         if(x&1) a = mul(a, b);
22         b = mul(b, b);
23         x >>= 1;
24     }
25     return a;
26 }
27 int main(){
28     while(scanf("%d%d%d%d", &n, &mod, &d, &k) == 4){
29         num = 1;
30         for(int i = 0; i < n; ++i) scanf("%lld", a+i);
31         for(int i = 0; i < n; ++i){
32             m[0][i] = i == 0 ? 1 : 0;
33             m[1][i] = (i <= d || i >= n-d) ? 1 : 0;
34         }
35         int x = q_m(k);
36         for(int i = 0; i < n; ++i){
37             ll sum = 0;
38             for(int j = 0; j < n; ++j){
39                 sum = (sum + (a[j]*m[x][(n-i+j)%n])%mod) % mod;
40             }
41             if(i != n-1) printf("%lld ", sum);
42             else printf("%lld\n", sum);
43         }
44     }
45     return 0;
46 }

 

 

--------------------------------------------------------------------------------------------------------------------

 

 

 http://acm.hdu.edu.cn/showproblem.php?pid=2256

 

盗图

 

 

(/2 + /3)^2*n  = = (5+2/6)^n;

(5+2/6)^n + (5-2/6)^n = 1 

 

 

 

 1 #include <iostream>
 2 #include <cmath>
 3 using namespace std;
 4 struct Node{
 5     int x[2][2];
 6 };
 7 int n;
 8 const int MOD = 1024;
 9 Node mul(Node x, Node y){
10     Node X;
11     X.x[0][0] = X.x[0][1] = X.x[1][0] = X.x[1][1] = 0;
12     for(int i = 0; i < 2; ++i){
13         for(int j = 0; j < 2; ++j){
14             for(int k = 0; k < 2; ++k){
15                 X.x[i][j] = (X.x[i][j] + x.x[i][k]*y.x[k][j]%MOD)%MOD;
16             }
17         }
18     }
19     return X;
20 }
21 Node q_m(Node A, int x){
22     Node AA;
23     AA.x[0][0] = AA.x[1][1] = 1;
24     AA.x[0][1] = AA.x[1][0] = 0;
25     while(x){
26         if(x&1) AA = mul(AA, A);
27         A = mul(A, A);
28         x >>= 1;
29     }
30     return AA;
31 }
32 int main(){
33     int t;
34     scanf("%d", &t);
35     while(t--){
36         scanf("%d", &n);
37         Node A;
38         A.x[0][0] = A.x[1][1] = 5;
39         A.x[0][1] = 12, A.x[1][0] = 2;
40         Node AA = q_m(A, n);
41         //printf("%d\n", (AA.x[0][0]+(int)floor((double)AA.x[1][0]*sqrt(6.0)))%MOD);
42         printf("%d\n", (2*AA.x[0][0]-1)%MOD);
43     }
44     return 0;
45 }

 

 

--------------------------------------------------------------------------------------------------------------------

 

 

 http://acm.hdu.edu.cn/showproblem.php?pid=4565

 

 套路题

 

(X,Y,Z)|A| = (X', Y', Z')

 

 1 #include <iostream>
 2 using namespace std;
 3 #define ll long long
 4 ll a, b, n, m;
 5 struct Node{
 6     ll x[2][2];
 7 };
 8 Node mul(Node xx, Node yy){
 9     Node AAA;
10     for(int i = 0; i < 2; ++i){
11         for(int j = 0; j < 2; ++j){
12             AAA.x[i][j] = 0;
13             for(int k = 0; k < 2; ++k){
14                 AAA.x[i][j] = (AAA.x[i][j] + xx.x[i][k]*yy.x[k][j]%m)%m;
15             }
16         }
17     }
18     return AAA;
19 }
20 Node q_m(Node A, int x){
21     Node AA;
22     AA.x[0][0] = AA.x[1][1] = 1;
23     AA.x[0][1] = AA.x[1][0] = 0;
24     while(x){
25         if(x&1) AA = mul(AA, A);
26         A = mul(A, A);
27         x >>= 1;
28     }
29     return AA;
30 }
31 int main(){
32     while(~scanf("%lld%lld%lld%lld", &a, &b, &n, &m)){
33         Node A;
34         A.x[0][0] = a, A.x[0][1] = 1;
35         A.x[1][0] = b, A.x[1][1] = a;
36         Node AA = q_m(A, n);
37         //cout<<AA.x[0][0]<<endl;
38         printf("%lld\n", 2*(AA.x[0][0])%m);
39     }
40     return 0;
41 }

 

 

--------------------------------------------------------------------------------------------------------------------

 

http://acm.hdu.edu.cn/showproblem.php?pid=4291

 

矩阵幂次幂,,找循环节。。。。。。看别人的代码才相通的,还是自己太菜

 

 1 #include <iostream>
 2 using namespace std;
 3 #define ll long long
 4 ll Mod;
 5 ll Mo[3] = {183120LL, 222222224LL, 1000000007LL};
 6 ll a[3];
 7 ll call(ll x){
 8     a[0] = 0LL, a[1] = 1LL, a[2] = 3LL;
 9     for(ll i = 3LL; ;i++){
10         a[i%3] = (3LL*a[(i-1)%3]+a[(i-2)%3])%x;
11         if(a[i%3] == 3LL && a[(i-1)%3] == 1LL) return i-2;
12     }
13 }
14 ll n;
15 struct Node{
16     ll x[2][2];
17 };
18 Node mul(Node xx, Node yy){
19     Node AAA;
20     for(int i = 0; i < 2; ++i){
21         for(int j = 0; j < 2; ++j){
22             AAA.x[i][j] = 0;
23             for(int k = 0; k < 2; ++k){
24                 AAA.x[i][j] = (AAA.x[i][j] + xx.x[i][k]*yy.x[k][j]%Mod)%Mod;
25             }
26         }
27     }
28     return AAA;
29 }
30 ll q_m(ll x){
31     for(int i = 0; i < 3; ++i){
32         Mod = Mo[i];
33         Node AA, A;
34         AA.x[0][0] = AA.x[1][1] = 1;
35         AA.x[0][1] = AA.x[1][0] = 0;
36         A.x[0][0] = 3, A.x[0][1] = 1;
37         A.x[1][0] = 1, A.x[1][1] = 0;
38         while(x){
39             if(x&1) AA = mul(AA, A);
40             A = mul(A, A);
41             x >>= 1;
42         }
43         x = AA.x[0][0]-1;
44         if(x == -1) return 0;
45     }
46     return x+1;
47 }
48 int main(){
49     while(~scanf("%lld", &n)){
50         if(n == 0){
51             puts("0");
52             continue;
53         }
54         //Node AA = q_m(A, n-1);
55         //cout<<AA.x[0][0]<<endl;
56         printf("%lld\n", q_m(n-1));
57         //cout<<call(Mod)<<endl;//222222224
58         //cout<<call(222222224LL)<<endl;//183120
59     }
60     return 0;
61 }

 

 

 

--------------------------------------------------------------------------------------------------------------------

 

http://poj.org/problem?id=3233

求矩阵一次方加到k次方对m取模

等差数列用二分

 

 1 #include <stdio.h>
 2 #include <iostream>
 3 #include <string.h>
 4 using namespace std;
 5 #define ll long long
 6 int n, k, m;
 7 struct Node{
 8     int x[31][31];
 9 }A;
10 Node Sum(Node a, Node b){
11     for(int i = 0; i < n; ++i){
12         for(int j = 0; j < n; ++j){
13             a.x[i][j] = (a.x[i][j] + b.x[i][j])%m;
14         }
15     }
16     return a;
17 }
18 Node mul(Node a, Node b){
19     Node B;
20     for(int i = 0; i < n; ++i){
21         for(int j = 0; j < n; ++j){
22             B.x[i][j] = 0;
23             for(int k = 0; k < n; ++k){
24                 B.x[i][j] = (B.x[i][j] + a.x[i][k]*b.x[k][j]%m)%m;
25             }
26         }
27     }
28     return B;
29 }
30 Node q_m(Node AAA, Node A, ll x){
31     while(x){
32         if(x&1) AAA = mul(AAA, A);
33         A = mul(A, A);
34         x >>= 1;
35     }
36     return AAA;
37 }
38 void solve(){
39     Node AA, AAA, X;
40     for(int i = 0; i < n; ++i){
41         for(int j = 0; j < n; ++j){
42             AA.x[i][j] = 0;
43             X.x[i][j] = AAA.x[i][j] = (i == j);
44         }
45     }
46     while(k > 1){
47         if(k&1){
48             AA = Sum(AA, mul(X, q_m(AAA, A, k))); //开始q_m没有乘X导致WA了好几次
49         }
50         k >>= 1;
51         X = mul(Sum(AAA, q_m(AAA, A, k)), X);
52     }
53     X = Sum(mul(A, X), AA);
54     for(int i = 0; i < n; ++i){
55         for(int j = 0; j < n; ++j){
56             printf("%d%c", X.x[i][j], (j == n-1 ? '\n' : ' '));
57         }
58     }
59 }
60 int main(){
61     while(~scanf("%d%d%d", &n, &k, &m)){
62         for(int i = 0; i < n; ++i){
63             for(int j = 0; j < n; ++j){
64                 scanf("%d", &A.x[i][j]);
65             }
66         }
67         solve();
68     }
69     return 0;
70 }

 

 构造矩阵,,woc,这也能构造????,,,厉害了。。。。

设    |A A| 为X

     |0 I |

 

 (I, 0) X = (A, A);  (A, A) X = (A^2, A^2+A)........

 1 #include <iostream>
 2 #include <string.h>
 3 using namespace std;
 4 const int maxn = 62;
 5 int A[maxn][maxn], B[maxn][maxn];
 6 int n, k, m, x;
 7 void mul(int a[maxn][maxn], int b[maxn][maxn], int x){
 8     int y[maxn][maxn];
 9     for(int i = 0; i < x; ++i){
10         for(int j = 0; j < x; ++j){
11             y[i][j] = 0;
12             for(int k = 0; k < x; ++k){
13                 y[i][j] = (y[i][j] + a[i][k]*b[k][j]%m)%m;
14             }
15         }
16     }
17     memcpy(a, y, sizeof(y));
18 }
19 void q_m(int x, int xx){
20     for(int i = 0; i < x; ++i){
21         for(int j = 0; j < x; ++j){
22             B[i][j] = (i == j);
23         }
24     }
25     while(xx){
26         if(xx&1) mul(B, A, x);
27         mul(A, A, x);
28         xx >>= 1;
29     }
30     for(int i = 0; i < n; ++i){
31         for(int j = n; j < x; ++j){
32             printf("%d%c", B[i][j], (j == x-1 ? '\n' : ' '));
33         }
34     }
35 }
36 int main(){
37     while(~scanf("%d%d%d", &n, &k, &m)){
38         memset(A, 0, sizeof(A));
39         for(int i = 0; i < n; ++i){
40             for(int j = 0; j < n; ++j){
41                 scanf("%d", &x);
42                 A[i][j] = A[i][n+j] = x;
43             }
44             A[i+n][i+n] = 1;
45         }
46         q_m(2*n, k);
47     }
48     return 0;
49 }

 

 

 

 

 下面的代码是二分写的,上面是构造矩阵的。很明显,,构造的代码不但简单好写而且耗时短,比二分快了将近三倍。。。6666666

看来还是构造吊一点。。毕竟一次快速幂就可以出来,而二分的话要多次快速幂。。。。

 

 

--------------------------------------------------------------------------------------------------------------------

 

 

http://acm.hdu.edu.cn/showproblem.php?pid=5667

 

矩阵快速幂加费马定理

 

 1 #include <iostream>
 2 using namespace std;
 3 #define ll long long
 4 ll n, a, b, c, p, Mod;
 5 struct Node{
 6     ll x[3][3];
 7 };
 8 Node mul(Node a, Node b){
 9     Node B;
10     for(int i = 0; i < 3; ++i){
11         for(int j = 0; j < 3; ++j){
12             B.x[i][j] = 0;
13             for(int k = 0; k < 3; ++k){
14                 B.x[i][j] = (B.x[i][j] + a.x[i][k]*b.x[k][j]%Mod)%Mod;
15             }
16         }
17     }
18     return B;
19 }
20 ll Q_m(ll a, ll x){
21     if(a == 0) return 0;
22     ll X = 1LL;
23     while(x){
24         if(x&1) X = X*a%p;
25         a = a*a%p;
26         x >>= 1;
27     }
28     return X;
29 }
30 void q_m(){
31     Node A, AA;
32     Mod = p-1LL;
33     for(int i = 0; i < 3; ++i){
34         for(int j = 0; j < 3; ++j){
35             AA.x[i][j] = (i == j);
36             A.x[i][j] = 0LL;
37         }
38     }
39     A.x[1][1] = c%Mod;
40     A.x[1][0] = A.x[2][1] = A.x[0][1] = A.x[2][2] = 1LL;
41     n --;
42     while(n){
43         if(n&1) AA = mul(AA, A);
44         A = mul(A, A);
45         n >>= 1;
46     }
47     /*
48     for(int i = 0; i < 3; ++i){
49         for(int j = 0; j < 3; ++j){
50             printf("%lld%c", AA.x[i][j], (j == 2 ? '\n' : ' '));
51         }
52     }
53     */
54     b%=Mod;
55     printf("%lld\n", Q_m(a%p, ((AA.x[1][0]+AA.x[2][0])%Mod)*b%Mod));
56 }
57 int main(){
58     int t;
59     scanf("%d", &t);
60     while(t--){
61         scanf("%lld%lld%lld%lld%lld", &n, &a, &b, &c, &p);
62         q_m();
63     }
64     return 0;
65 }

 

 

--------------------------------------------------------------------------------------------------------------------

 

http://acm.hdu.edu.cn/showproblem.php?pid=5451

 

一个网络赛的题目,,,漩斌大神可是十分钟就A的题,。。。我太菜!!!!!!!!!

 

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 using namespace std;
 5 #define ll long long
 6 ll n, m, Mod;
 7 int a[50000];
 8 bool vis[50000];
 9 struct Node{
10     ll x[2][2];
11 };
12 int w = 1;
13 ll Q_m(){
14     ll X = 1LL, x = 2LL;
15     while(n){
16         if(n&1) X = X*x%Mod;
17         x = x*x%Mod;
18         n >>= 1;
19     }
20     return X;
21 }
22 Node mul(Node a, Node b){
23     Node B;
24     for(int i = 0; i < 2; ++i){
25         for(int j = 0; j < 2; ++j){
26             B.x[i][j] = 0;
27             for(int k = 0; k < 2; ++k){
28                 B.x[i][j] = (B.x[i][j] + a.x[i][k]*b.x[k][j]%Mod)%Mod;
29             }
30         }
31     }
32     return B;
33 }
34 ll get(Node A, Node AA){
35     for(ll i = 1; ; ++i){
36      //cout<<"*********"<<endl;
37         AA = mul(A, AA);
38         if(AA.x[0][0] == 5%Mod && AA.x[0][1] == 2%Mod && AA.x[1][0] == 12%Mod && AA.x[1][1] == 5%Mod){
39            // cout<<i<<"***************"<<endl;
40             return i;
41         }
42     }
43 }
44 void q_m(){
45     Node A, AA;
46     AA.x[0][0] = AA.x[1][1] = 1LL;
47     AA.x[1][0] = AA.x[0][1] = 0;
48     A.x[0][0] = A.x[1][1] = 5LL;
49     A.x[0][1] = 2LL, A.x[1][0] = 12LL;
50     if(!vis[m]){
51         Mod = m;
52         Mod = get(A, A);
53         vis[m] = true;
54         a[m] = Mod;
55     }else{
56         Mod = a[m];
57     }
58     ll x = Q_m()+1LL;
59     Mod = m;
60     while(x){
61         if(x&1) AA = mul(AA, A);
62         A = mul(A, A);
63         x >>= 1;
64     }
65     printf("Case #%d: %lld\n", w++, (2LL*AA.x[0][0]%Mod-1LL+Mod)%Mod);
66 }
67 int main(){
68     int t;
69     scanf("%d", &t);
70     while(t--){
71         scanf("%lld%lld", &n, &m);
72         q_m();
73     }
74     return 0;
75 }

 

该题循环节为 (m+1)*(m-1)

细节参考

关于斐波那契数列的循环节:http://blog.csdn.net/acdreamers/article/details/25616461

 

 

--------------------------------------------------------------------------------------------------------------------

中南邀请赛(湘潭) http://202.197.224.59/OnlineJudge2/index.php/Problem/read/id/1243

 

找循环节。。

挖了好次,有几个特例。。。。

 

  1 #include <iostream>
  2 #include <string.h>
  3 #include <stdio.h>
  4 using namespace std;
  5 #define ll long long
  6 struct Node{
  7     int x[2][2];
  8 };
  9 Node T, M;
 10 int Mod;
 11 char str[100009];
 12 Node mul(Node a, Node b){
 13     Node c;
 14     for(int i = 0; i < 2; ++i){
 15         for(int j = 0; j < 2; ++j){
 16             c.x[i][j] = 0;
 17             for(int k = 0; k < 2; ++k){
 18                 c.x[i][j] = (c.x[i][j] + a.x[i][k]*b.x[k][j]%7)%7;
 19             }
 20         }
 21     }
 22     return c;
 23 }
 24 void read(Node b){
 25     for(int i = 0; i < 2; ++i){
 26         for(int j = 0; j < 2; ++j){
 27             if(j == 1) printf("%d\n", b.x[i][j]);
 28             else printf("%d ", b.x[i][j]);
 29         }
 30     }
 31 }
 32 bool go(){
 33     //read(T);
 34     for(int i = 2; ; ++i){
 35         //cout<<"&&"<<endl;
 36         M = mul(T, M);
 37         if(!M.x[0][0] && !M.x[0][1] && !M.x[1][0] &&!M.x[1][1]){
 38             //read(T);
 39             //printf("%d******\n", i);
 40             return false;
 41         }
 42         if(M.x[0][0] == T.x[0][0] && M.x[0][1] == T.x[0][1] && M.x[1][0] == T.x[1][0] && M.x[1][1] == T.x[1][1]){
 43             Mod = i - 1;
 44             //printf("%d%%%%\n", i);
 45             return true;
 46         }
 47     }
 48 }
 49 void q(Node a, ll x){
 50     Node b;
 51     b.x[0][0] = b.x[1][1] = 1;
 52     b.x[0][1] = b.x[1][0] = 0;
 53     while(x){
 54         if(x&1) b = mul(b, a);
 55         a = mul(a, a);
 56         x >>= 1;
 57     }
 58     read(b);
 59 }
 60 
 61 void lala(int x){
 62     if(x == 4){
 63         M.x[0][0] = T.x[0][0], M.x[0][1] = T.x[0][1];
 64         M.x[1][0] = T.x[1][0], M.x[1][1] = T.x[1][1];
 65         go();
 66         return ;
 67     }
 68     for(int i = 0; i < 7; ++i){
 69         //cout<<i<<"**"<<x<<endl;
 70         T.x[x/2][x%2] = i;
 71         lala(x+1);
 72     }
 73 }
 74 
 75 int main(){
 76     //lala(0);
 77     while(~scanf(" %s", str)){
 78         int x, y, z, w;
 79         scanf("%d%d%d%d", &x, &y, &z, &w);
 80         T.x[0][0] = M.x[0][0] = x, T.x[0][1] = M.x[0][1] = y;
 81         T.x[1][0] = M.x[1][0] = z, T.x[1][1] = M.x[1][1] = w;
 82         int len = strlen(str);
 83         if(!go()){
 84             if(len == 1 && str[0] == '1') printf("%d %d\n%d %d\n", x, y, z, w);
 85             else printf("0 0\n0 0\n");
 86             continue;
 87         }
 88         //printf("%d****\n", Mod);
 89         if(Mod == 1){
 90             printf("%d %d\n%d %d\n", x, y, z, w);
 91             continue;
 92         }
 93         ll sum = 0;
 94         for(int i = 0; i < len; ++i){
 95             //cout<<sum<<" "<<i<<endl;
 96             sum = (sum*10+str[i]-'0')%Mod;
 97         }
 98         //cout<<sum<<endl;
 99         q(T, sum);
100     }
101     return 0;
102 }

 

--------------------------------------------------------------------------------------------------------------------

--------------------------------------------------------------------------------------------------------------------

--------------------------------------------------------------------------------------------------------------------

 

 

只有不断学习才能进步!

 

转载于:https://www.cnblogs.com/wenbao/p/6506556.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值