bzoj 2326: [HNOI2011]数学作业

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cmath>
 5 #define ll long long
 6 ll b[20],x[3][3],y[3][3],n,a[20],ans,ans1,m;
 7 void cheng(ll q[3][3],ll q1[3][3])
 8 {
 9     ll q2[3][3];
10     memset(q2,0,sizeof(q2));
11     for(int i=0;i<3;i++)
12       for(int j=0;j<3;j++)
13         for(int k=0;k<3;k++)
14           q2[i][j]=(q2[i][j]+(q[i][k]*q1[k][j])%m)%m;
15     for(int i=0;i<3;i++)
16       for(int j=0;j<3;j++)
17         q[i][j]=q2[i][j];
18     return;
19 }
20 int main()
21 {
22     scanf("%lld%lld",&n,&m);
23     b[0]=1;
24     for(int i=1;i<=18;i++)
25       {
26         b[i]=(b[i-1]*10);
27         if(n>=b[i])
28           a[0]=i;
29       }
30     a[0]++;
31     if(n<10)
32       a[1]=n;
33     else
34       a[1]=9;
35     for(int i=2;i<a[0];i++)
36       a[i]=a[i-1]*10;
37     if(n>=10)
38       a[a[0]]=n-b[a[0]-1]+1;
39     for(int i=1;i<=a[0];i++)
40       {
41         memset(x,0,sizeof(x));
42         x[2][1]=x[2][0]=x[1][1]=x[1][0]=x[0][0]=1;
43         memset(y,0,sizeof(y));
44         x[2][2]=b[i]%m;
45         y[0][0]=y[1][1]=y[2][2]=1;
46         ll k=a[i];
47         for(;k;)
48           {
49             if(k%2)
50               cheng(y,x);
51             cheng(x,x);
52             k/=2;
53           }
54         ans=(y[2][0]+(y[2][1]*ans1)%m+(y[2][2]*ans)%m)%m;
55         ans1=(y[1][0]+(ans1*y[1][1])%m)%m;
56       }
57     printf("%lld
",ans);
58     return 0;
59 }

这是个矩阵乘法 对相同的位数构建一个矩阵。

原文地址:https://www.cnblogs.com/xydddd/p/5300213.html