hdu 5564 Clarke and digits 矩阵快速幂优化数位dp Clarke and digits

hdu 5564 Clarke and digits 矩阵快速幂优化数位dp
Clarke and digits

Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)



Problem Description
Clarke is a patient with multiple personality disorder. One day, Clarke turned into a researcher, did a research on digits. 
He wants to know the number of positive integers which have a length in k.
 
Input
The first line contains an integer ).
 
Output
Each test case print a line with a number, the answer modulo 7.
 
Sample Input
2 1 2 5 2 3 5
 
Sample Output
13 125 Hint: At the first sample there are 13 number $7,21,28,35,42,49,56,63,70,77,84,91,98$ satisfied.
 
Source

思路:显然数位,dp[ i ][ j ][ pre ]+=dp[ i-1 ][ j1 ][ pre1 ] &&pre1+pre!=k&&0<=k<=9&&(j1%10+pre)%7==j

   但是r太大,考虑矩阵优化;

   

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<queue>
#include<algorithm>
#include<stack>
#include<cstring>
#include<vector>
#include<list>
#include<bitset>
#include<set>
#include<map>
#include<time.h>
using namespace std;
#define LL long long
#define bug(x)  cout<<"bug"<<x<<endl;
const int N=5e4+10,M=1e6+10,inf=1e9+10,MOD=1e9+7;
const LL INF=1e18+10,mod=1e9+7;
const double eps=(1e-8),pi=(4*atan(1.0));

struct Matrix
{
    const static int row=71;
    int a[row][row];//矩阵大小根据需求修改
    Matrix()
    {
        memset(a,0,sizeof(a));
    }
    void init()
    {
        for(int i=0;i<row;i++)
            for(int j=0;j<row;j++)
                a[i][j]=(i==j);
    }
    Matrix operator + (const Matrix &B)const
    {
        Matrix C;
        for(int i=0;i<row;i++)
            for(int j=0;j<row;j++)
                C.a[i][j]=(a[i][j]+B.a[i][j])%MOD;
        return C;
    }
    Matrix operator * (const Matrix &B)const
    {
        Matrix C;
        for(int i=0;i<row;i++)
            for(int k=0;k<row;k++)
                for(int j=0;j<row;j++)
                    C.a[i][j]=(C.a[i][j]+1LL*a[i][k]*B.a[k][j])%MOD;
        return C;
    }
    Matrix operator ^ (const int &t)const
    {
        Matrix A=(*this),res;
        res.init();
        int p=t;
        while(p)
        {
            if(p&1)res=res*A;
            A=A*A;
            p>>=1;
        }
        return res;
    }
};
Matrix base,one;
void init(int k)
{
    memset(base.a,0,sizeof(base.a));
    for(int i=0;i<70;i++)
    {
        int x=(i/10);
        int y=(i%10);
        for(int j=0;j<70;j++)
        {
            int x1=j/10;
            int y1=j%10;
            if((y+x1*10)%7==x&&y1+y!=k)
                base.a[j][i]=1;
        }
    }
    for(int i=0;i<10;i++)base.a[i][70]=1;
    base.a[70][70]=1;
}
int main()
{
    memset(one.a,0,sizeof(one.a));
    for(int i=1;i<10;i++)one.a[0][(i%7)*10+i]=1;
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int l,r,k;
        scanf("%d%d%d",&l,&r,&k);
        init(k);
        Matrix ansr=one*(base^(r));
        Matrix ansl=one*(base^(l-1));
        LL out=ansr.a[0][70]-ansl.a[0][70];
        out=(out%mod+mod)%mod;
        printf("%lld
",out);
    }
    return 0;
}