HDU 5451 Best Solver

没有意识到循环节最大是M^2,用域Z_M下二阶可逆矩阵群的最大循环节(M^2-1)*(M^2-M)来做,考虑大数乘法,矩阵乘法,做到吐血。将代码贴在下方留作纪念。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define rep(i,a,b) for(int i=a;i<=b;++i)
 4 #define ms(arr,a) memset(arr,a,sizeof arr)
 5 long long P;
 6 long long M;
 7 long long x;
 8 long long modM(long long x)
 9 {
10     if(x<0)return x%M+M;
11     else return x%M;
12 }
13 struct matrix
14 {
15     long long a,b,c,d;
16     matrix(){}
17     matrix(long long m,long long n,long long p,long long q):a(m),b(n),c(p),d(q){}
18     matrix(long long x):a(x),b(0),c(0),d(x){}
19 };
20 matrix solve(matrix A,matrix B)
21 {
22     matrix ret;
23     ret.a=modM(A.a*B.a+A.b*B.c);
24     ret.b=modM(A.a*B.b+A.b*B.d);
25     ret.c=modM(A.c*B.a+A.d*B.c);
26     ret.d=modM(A.c*B.b+A.d*B.d);
27     return ret;
28 }
29 long long solve(long long x,long long y)
30 {
31     long long ret=0;
32     while(x)
33     {
34         if(x&1)ret=(ret+y)%P;
35         y=(2*y)%P;
36         x>>=1;
37     }
38     return ret;
39 }
40 template<typename T>
41 T quick_pow(T a,long long n)
42 {
43     T ret(1);
44     while(n)
45     {
46         if(n&1)ret=solve(ret,a);
47         a=solve(a,a);
48         n>>=1;
49     }
50     return ret;
51 }
52 int main()
53 {
54     int T;scanf("%d",&T);
55     rep(Case,1,T)
56     {
57         scanf("%lld%lld",&x,&M);
58         P=(M*M-1)*(M*M-M);
59         long long N=(quick_pow(2LL,x)+1)%P;
60         //printf("%lld
",N);
61         matrix tmp=(matrix){10,-1,1,0};
62         tmp=quick_pow(tmp,N);
63         printf("Case #%d: %lld
",Case,modM(tmp.c*10+tmp.d*2-1));
64     }
65 }
原文地址:https://www.cnblogs.com/maoruimas/p/9514804.html