bzoj 2326: [HNOI2011]数学作业(矩阵快速幂)

来源:互联网 发布:openbugs软件 编辑:程序博客网 时间:2024/05/12 06:38

2326: [HNOI2011]数学作业

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 2249  Solved: 1301
[Submit][Status][Discuss]

Description


令F(n) = Concatenate(1, n)

那么有

F(x) = F(x-1)*10+(x-1)+1     x∈(1, 9)

F(x) = F(x-1)*100+(x-1)+1     x∈(10, 99)

F(x) = F(x-1)*1000+(x-1)+1     x∈(100, 999)

F(x) = F(x-1)*10000+(x-1)+1     x∈(1000, 9990)

……

其中最多18段(题目中没有n=10^18这组数据)

每一段的公式都可以转成对应的矩阵快速幂

这样复杂度就是O(logn)了

矩阵方程:



#include<stdio.h>#include<string.h>#define LL long longtypedef struct{LL a[4][4];void init(LL x){memset(a, 0, sizeof(a));a[1][1] = x;a[2][1] = a[2][2] = a[3][1] = a[3][2] = a[3][3] = 1;}void unit(){memset(a, 0, sizeof(a));a[1][1] = a[2][2] = a[3][3] = 1;}}Matrix;Matrix Jz;LL ans[4], temp[4];Matrix Mult(Matrix A, Matrix B, LL mod){LL i, j, k;Matrix C;memset(C.a, 0, sizeof(C.a));for(i=1;i<=3;i++){for(j=1;j<=3;j++){for(k=1;k<=3;k++)C.a[i][j] = (C.a[i][j]+A.a[i][k]*B.a[k][j])%mod;}}return C;}Matrix Pow(Matrix A, LL b, LL mod){Matrix C;C.unit();while(b){if(b%2)C = Mult(C, A, mod);A = Mult(A, A, mod);b /= 2;}return C;}int main(void){LL n, m, i, j, k, flag;while(scanf("%lld%lld", &n, &m)!=EOF){ans[1] = ans[2] = 0;ans[3] = 1;flag = 0;if(n==(LL)1e18-1)flag = 1, n--;for(i=9;i<=n&&i>=9;i=i*10+9){Jz.init((i+1)%m);Jz = Pow(Jz, (i+1)/10*9, m);temp[1] = ans[1], temp[2] = ans[2], temp[3] = ans[3];ans[1] = ans[2] = ans[3] = 0;for(j=1;j<=3;j++){for(k=1;k<=3;k++)ans[j] = (ans[j]+temp[k]*Jz.a[k][j])%m;}}Jz.init((i+1)%m);Jz = Pow(Jz, n-(i-9)/10, m);temp[1] = ans[1], temp[2] = ans[2], temp[3] = ans[3];ans[1] = ans[2] = ans[3] = 0;for(j=1;j<=3;j++){for(k=1;k<=3;k++)ans[j] = (ans[j]+temp[k]*Jz.a[k][j])%m;}if(flag==1)ans[1] = (ans[1]*((LL)1e18%m)+((LL)1e18-1)%m)%m;printf("%lld\n", ans[1]%m);}return 0;}

原创粉丝点击