P3216 [HNOI2011] math homework
... looked segments
Let k be the number of digits
1--9 ->k=1
10--99 ->k=2
100--999->k=3
So recursive formula
So matrix becomes:
10^k | 0 | 0 |
---|---|---|
1 | 1 | 0 |
1 | 1 | 1 |
However, the matrix becomes longer, how to do it, we can be handled separately, initial matrix f [ 0 ] => (0,0,1)
Enumeration from 1 digit up to the length (n) -1-bit, 10k matrix multiplication has 9 * 10k-1 times.
Finally, treatment length (n) bits, multiplied 10length (n) matrix of n-Σlength (n) k = 1 (9 * 10k-1) times.
Spend more than one hour to finish, pay a 40 ...
Adjust two hours only to find the definition of ull, scanf% d ................. became a hit in the dish
So from Dev opened the biggest mistakes in the warning ...
AC 码
#include<cstdio>
#include<cstring>
#include<algorithm> #define ull unsigned long long using namespace std; ull n,m,po[25],lim[25]; struct MAT { ull a[3][3]; MAT() {memset(a,0,sizeof a);} }tran,ans; void pre() { tran.a[0][1]=1,tran.a[0][2]=1; tran.a[1][0]=0,tran.a[1][1]=1,tran.a[1][2]=1; tran.a[2][0]=0,tran.a[2][1]=0,tran.a[2][2]=1; po[0]=0,po[1]=1; for (int i=2; i<=19; i++) { po[i]= po [i- 1 ] * 10 ; } Paste [ 0 ] = 1 ; for ( int i = 1 ; i <= 18 ; i ++ ) { paste [i] = paste [i- 1 ] * 10 ; } Paste [ 0 ] = 2 ; ans.a [ 0 ] [ 0 ] = 1 , ans.a [ 1 ] [ 0 ] = 1 , ans.a [ 2 ] [ 0 ] = 1 ; } MAT mul(MAT u,MAT v) { MAT w; int i,j,k; for (i=0;i<3;i++) for (j=0;j<3;j++) for (k=0;k<3;k++) (w.a[i][j]+=u.a[i][k]*v.a[k][j])%=m; return w; } MAT pow(MAT b,ull p) { if(p==1) return b; MAT t=pow(b,p/2); t=mul(t,t); return p%2==0?t:mul(t,b); } int main() { scanf("%lld%lld",&n,&m),pre(); for (int i=1; i<=18; i++) { if (lim[i-1]<=n) { tran.a[0][0]=po[i+1]%m; if (i<18&&lim[i]-1<=n) ans=mul(pow(tran,lim[i]-lim[i-1]),ans); else if (lim[i]>n) ans=mul(pow(tran,n-lim[i-1]+1),ans); } else break; } printf("%lld\n",ans.a[0][0]); return 0; }
2019-07-30 00:57:02
Code is still something not clear, write tomorrow