[BZOJ 2326][HNOI2011]数学作业
2326: [HNOI2011]数学作业
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 2395 Solved: 1396
[Submit][Status][Discuss]Description
Input
Output
Sample Input
Sample Output
题解
这题看起来还是很一颗赛艇的...
一看数据范围大概就知道是个 $O(\log(n))$ 或者 $O(1)$ 好题了OwO
这题的滑稽之处在于这题它...emmmm...矩阵会变=.=
大概需要在每个 $[10^k,10^{k+1})$ 都用自己的矩阵跑一遍快速幂.
矩阵大概长这样:
\[\begin{bmatrix}10^{k+1} & 1 & 1\\ 1 & 1 & 0\\ 1 & 0 & 1\end{bmatrix}\]
然后注意一下边界条件以及分层的时候每层的区间左闭右开就好了...
(被左闭右开坑到死然后一直找不到错对拍随机数据还拍不出来甚至标程跑炸了都拍不出)
参考代码
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 7 long long n,p; 8 long long v[3]={0,0,1}; 9 10 void Calc(long long,long long); 11 12 int main(){ 13 scanf("%lld%lld",&n,&p); 14 long long t=10; 15 while(n>=t){ 16 Calc(t,t-t/10); 17 t*=10; 18 } 19 Calc(t,n-t/10+1); 20 printf("%lld\n",v[0]); 21 return 0; 22 } 23 24 void Calc(long long k,long long t){ 25 long long vt[3],mt[3][3]; 26 long long m[3][3]={{k%p,0,0},{1,1,0},{1,1,1}}; 27 while(t>0){ 28 if((t&1)!=0){ 29 memset(vt,0,sizeof(vt)); 30 for(int i=0;i<3;++i){ 31 for(int j=0;j<3;++j){ 32 (vt[j]+=v[i]*m[i][j])%=p; 33 } 34 } 35 memcpy(v,vt,sizeof(vt)); 36 } 37 memset(mt,0,sizeof(mt)); 38 for(int i=0;i<3;++i){ 39 for(int j=0;j<3;++j){ 40 for(int k=0;k<3;++k){ 41 (mt[i][j]+=m[i][k]*m[k][j])%=p; 42 } 43 } 44 } 45 memcpy(m,mt,sizeof(mt)); 46 t>>=1; 47 } 48 }
本博客已弃用, 新个人主页: https://rvalue.moe, 新博客: https://blog.rvalue.moe