2015年吉林省賽 Pin Pin Pin(矩陣快速冪)

bigbigship發表於2015-09-07

題意:

我們把1~n的數連著寫起來組成一個數,然後對1000000007取模f[1]=1,f[2]=12,..,f[9]=123456789...

n<=1e9,很明顯我們可以得到一個遞推式,f[n] = f[n-1]*k +n (k=10^(len(n))),由於n比較大我們需要用到矩陣來進行優化。


程式碼如下:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;

typedef long long LL;

const LL mod = 1e9+7;

const int maxn = 3;

struct matrix {
    LL m[maxn][maxn];
    matrix() {
        memset(m,0,sizeof(m));
    }
    matrix operator*(const struct matrix &A)const {
        matrix C;
        for(int i=0; i<maxn; i++) {
            for(int j=0; j<maxn; j++) {
                for(int k=0; k<maxn; k++) {
                    C.m[i][j]=(C.m[i][j]+A.m[i][k]*m[k][j]%mod)%mod;
                }
            }
        }
        return C;
    }
    friend matrix operator ^ (matrix a,int k) {
        matrix ans;
        for(int i = 0; i<maxn; i++)
            ans.m[i][i]=1;
        while(k) {
            if(k&1) ans = ans*a;
            k>>=1;
            a=a*a;
        }
        return ans;
    }
};

LL a[11];

matrix I;

void init() {
    a[0]=1;
    for(int i=1; i<11; i++) {
        a[i]=a[i-1]*(LL)10;
    }
    for(int i=0; i<maxn; i++) {
        I.m[i][i]=1;
    }
}

int main() {
    init();
    int t,n;
    scanf("%d",&t);
    while(t--) {
        scanf("%d",&n);
        matrix ans=I;
        matrix A;
        A.m[0][1]=1,A.m[0][2]=1;
        A.m[1][1]=1,A.m[1][2]=1;
        A.m[2][2]=1;
        for(int i=0; i<11&&a[i]<=n; i++) {
            int num;
            A.m[0][0]=a[i+1];
            if(a[i+1]<=n) num = a[i+1]-a[i];
            else num = n-a[i]+1;
            ans=ans*(A^num);
        }
        printf("%lld\n",ans.m[0][2]);
    }
    return 0;
}


相關文章