hihocoder1560 H国的身份证号码II

题意:输入n,m问满足条件的n位数有几个条件:首位不能为0,相邻的数乘积不能超过k,每一位数不能超过k

题解:10*10的矩阵

#include <bits/stdc++.h>
#define ll long long
#define maxn 10
using namespace std;
ll mod = 1e9+7;
struct mat{
    ll m[maxn][maxn], len;
    mat(){memset(m, 0, sizeof(m));len=maxn;}
    mat friend operator*(mat a,mat b){
        mat d;
        for(ll i=0;i<a.len;i++)
            for(ll j=0;j<b.len;j++)
                for(ll k=0;k<b.len;k++)
                d.m[i][j] = (d.m[i][j]%mod+(a.m[i][k]*b.m[k][j])%mod)%mod;
        return d;
    }
};
mat f(mat x,ll num){
    mat t;
    for(ll i=0;i<t.len;i++) t.m[i][i] = 1;
    while(num){
        if(num&1) t = t*x;
        x = x*x;
        num >>= 1;
    }
    return t;
}
ll ff(ll x,ll t,ll m){
    ll ans=1;
    while(t){
        if(t&1) ans = ans*x%m;
        x = x*x%m;
        t >>= 1;
    }
    return ans;
}
int main(){
    ll n,k, ans = 0;
    cin>>n>>k;
    mat t, fi;
    for(ll i=0;i<10;i++)
        for(ll j=0;j<10;j++){
            if(i*j<=k&&i<=k&&j<=k) t.m[i][j] = 1;
            else t.m[i][j] = 0;
        }
    for(ll i=0;i<10;i++)
        if(i<=k) fi.m[0][i] = 1;
    t = fi*f(t, n-1);
    for(int i=1;i<10;i++) ans = (ans+t.m[0][i])%mod;
    cout<<ans<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/Noevon/p/7401715.html