1. 程式人生 > >HDU5564 Clarke and digits

HDU5564 Clarke and digits

個數 dig 表示 hdu clas 構建 問題 inline span

前置知識

\(dp[i][j][k]\)表示\(i\)長,\(mod7=j\),這個位置選了\(k\)的方案數。

\(dp[i+1][(j*10+x)mod7][x]+=dp[i][j][y];//x+y!=K?\)

\(Ma.a[i][j]=1\)表示\(i\)狀態->\(j\)狀態可以轉移

如果設\(ans=qkpow(Ma,K)\)

\(ans.a[i][j]\)表示走\(K\)步之後狀態\(i\)到狀態\(j\)的方案數。

如果對這個不熟悉可以看看HDU5607

題解

然後對於本題而言,就要構建轉移的矩陣。

註意到對於後兩維而言,其實他們的轉移都是一樣的,與\(i\)沒有關系,而且其狀態只有7*10,所以可以構建\(70·70\)

的轉移矩陣。

初始矩陣就是第一位隨便填哪個數字都無所謂,所以

for(int i=1;i<10;i++)
    s.a[0][st(i%7,i)]=1;

接下來還有一個問題:如何統計前綴和?

我們要求的不僅僅是\(ans(R),ans(L)\)而是\(\sum_{i=L}^Rans(i)\)

所以,這裏有一個巧妙的操作:

for(int i=0;i<10;i++)
    Ma.a[i][70]=1;
Ma.a[70][70]=1;

這樣就可以保證我們最後要求的\(ans=\sum_{i=0}^9a[0][i]\)每一層都會被加到70這個點上,所以最後\(a[0][70]\)就是答案。

代碼

#include<bits/stdc++.h>
#define M 105
using namespace std;
const int mod=1e9+7;
int l,r,K,T;
struct Matrix{
    int n,m,a[M][M];
    void clear(){memset(a,0,sizeof(a));}
    void resize(int _n,int _m){n=_n;m=_m;}
    Matrix operator *(const Matrix &_)const{
        Matrix res;res.resize(n,_.m);
        for(int i=0;i<=n;i++){
            for(int j=0;j<=_.m;j++){
                res.a[i][j]=0;
                for(int k=0;k<=m;k++){
                    res.a[i][j]+=1LL*a[i][k]*_.a[k][j]%mod;
                    if(res.a[i][j]>=mod)res.a[i][j]-=mod;    
                }
            }
        }
        return res;
    }
}Ma,s;
Matrix qkpow(Matrix a,int b){
    Matrix res;res.clear();res.resize(a.n,a.n);
    for(int i=0;i<=a.n;i++)res.a[i][i]=1;
    while(b){if(b&1)res=res*a;a=a*a;b>>=1;}
    return res;
}
int st(int i,int j){return i*10+j;}
int main(){
    cin>>T;
    s.clear();s.resize(70,70);
    for(int i=1;i<10;i++)
        s.a[0][st(i%7,i)]=1;
    while(T--){
        scanf("%d%d%d",&l,&r,&K);
        Ma.clear();Ma.resize(70,70);
        for(int y=0;y<10;y++){
            for(int x=0;x<10;x++){
                if(x+y==K)continue;
                for(int j=0;j<7;j++){
                    Ma.a[st(j,y)][st((j*10+x)%7,x)]=1;
                }
            }
        }
        for(int i=0;i<10;i++)
            Ma.a[i][70]=1;
        Ma.a[70][70]=1;
        Matrix R=s*qkpow(Ma,r);
        Matrix L=s*qkpow(Ma,l-1);
        printf("%d\n",(R.a[0][70]-L.a[0][70]+mod)%mod);
    }
    return 0;
}

HDU5564 Clarke and digits