[bzoj2326][HNOI2011]数学作业

 来自FallDream的博客,未经允许,请勿转载,谢谢。


一个数接在后面的时候我们都可以看作乘以10的对应次方再加上这个数,所以考虑构造关于f(x),x矩阵,每次x还要加1,所以变成

(f[x] )        (10^k) (  1  ) (  1  )      (f[x+1])  

(  x  )    *   (  0   )  (  1  ) (  1  ) =   (  x+1 )   

(  1  )    (  0   )  (  0  ) (  1  )      (    1   )

对于不同的k分开处理

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
inline ll read()
{
    ll x = 0 , f = 1; char ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
    return x * f;
}

int mod,pw[19];
ll n;
struct Matrix
{
    int s[4][4],r,c;
    Matrix(){memset(s,0,sizeof(s));}
    Matrix(int y)
    {    
        memset(s,0,sizeof(s));r=c=3;
        s[1][1]=pw[y];s[1][2]=s[1][3]=1;
        s[2][3]=s[2][2]=s[3][3]=1;
    }
    Matrix(int a,int b)
    {
        memset(s,0,sizeof(s));r=3;c=1;
        s[1][1]=a;s[2][1]=b;s[3][1]=1;
    }
    Matrix operator*(Matrix b)
    {
        Matrix d;d.r=r;d.c=b.c;
        for(int i=1;i<=r;i++)
            for(int j=1;j<=c;j++)
                for(int k=1;k<=b.c;k++)
                    d.s[i][k]=(d.s[i][k]+1LL*s[i][j]*b.s[j][k])%mod;
        return d;
    }
}a(0,0);

void solve(int k,ll c)
{
    Matrix b(k);
    for(;c;c>>=1,b=b*b)
        if(c&1) a=b*a;
}

int main()
{
    n=read();mod=read();
    pw[1]=10%mod;
    for(int i=2;i<=18;i++) pw[i]=1LL*pw[i-1]*10%mod;
    for(ll i=9,last=0,j=1;n>last;++j,last=i,i=i*10+9)
        solve(j,min(i,n)-last);
    printf("%d
",a.s[1][1]);
    return 0;
}
原文地址:https://www.cnblogs.com/FallDream/p/bzoj2326.html