Bzoj2326 [HNOI2011]数学作业

 

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1819  Solved: 1074

Description

 

矩阵乘法会写不会用,悲伤

 

推出来递推式子是 f[i]=( f[i-1]*10^len[i]+i ) % mod

然后构造矩阵:

 [   f[i]  ]     [ 10^len[i]  1   1   ]     [ f[i-1]  ]

 [    i    ]  =   [     0         1   1   ]  *  [  i-1    ]

 [    1   ]       [     0         0    1  ]      [  1      ]

 

然而并不能出解。看了隔壁阿当的题解,发现运算的时候要改成这个样子:

  [  f[i]   0    0   ]

  [   0     1    0  ]

  [   0     0    1  ]

 

然后出解是在(1,3)位置。

 

 1 /*by SilverN*/
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<cmath>
 7 #define LL long long
 8 using namespace std;
 9 const int mxn=100010;
10 LL n,mod;
11 struct mat{
12     LL s[4][4];
13     mat(){memset(s,0,sizeof s);}
14 };
15 mat ans;
16 mat operator * (const mat a,const mat b){
17     mat c;
18     for(int i=1;i<=3;i++)
19      for(int j=1;j<=3;j++)
20       for(int k=1;k<=3;k++){
21           c.s[i][j]=(c.s[i][j]+a.s[i][k]*b.s[k][j])%mod;
22       }
23     return c;
24 }
25 inline void ksm(LL tmp,LL k){
26     mat res;
27     res.s[1][1]=tmp%mod;
28     res.s[1][2]=res.s[1][3]=res.s[2][2]=res.s[2][3]=res.s[3][3]=1;
29     k=k-tmp/10+1;
30     while(k){
31         if(k&1) ans=res*ans;
32         res=res*res;
33         k>>=1;
34     }
35     return;
36 }
37 int main(){
38     int i,j;
39     scanf("%lld%lld",&n,&mod);
40     for(i=1;i<=3;i++) ans.s[i][i]=1;
41     LL t=10;
42     for(;t<=n;t*=10)
43         ksm(t,t-1);
44     ksm(t,n);
45     /*
46     for(i=1;i<=3;i++){
47      for(j=1;j<=3;j++)printf("%d ",ans.s[i][j]);
48      printf("\n");
49     }
50     */
51     
52     printf("%lld\n",ans.s[1][3]);
53     return 0;
54 }

 

posted @ 2016-11-01 17:06  SilverNebula  阅读(224)  评论(0编辑  收藏  举报
AmazingCounters.com