Sam's Numbers(矩阵快速幂)

来源:互联网 发布:浪漫的c语言小程序 编辑:程序博客网 时间:2024/06/18 16:03

https://www.hackerrank.com/contests/hourrank-21/challenges/sams-numbers


#include<bits/stdc++.h>using namespace std;typedef long long ll;const int MOD = (int)1e9+9;ll s;int m,d,mm;struct Matrix{    ll mx[101][101];}one;Matrix mul(Matrix a,Matrix b){    Matrix re;    memset(re.mx,0,sizeof(re.mx));    for(int i=1;i<=mm;i++){        for(int k=1;k<=mm;k++){            if(a.mx[i][k]==0)continue;            for(int j=1;j<=mm;j++){                re.mx[i][j]+=a.mx[i][k]*b.mx[k][j]%MOD;                re.mx[i][j]%=MOD;            }        }    }    return re;}Matrix power(Matrix a,ll b){    Matrix re;    re=one;    while(b){        if(b&1)re=mul(re,a);        a=mul(a,a);        b>>=1;    }    return re;}int getidx(int x,int y){    return (x-1)*m+y;}ll fcc[111],ans[111];ll dp[11][11];int main(){    memset(one.mx,0,sizeof(one.mx));    for(int i=1;i<=100;i++)one.mx[i][i]=1;    while(~scanf("%lld%d%d",&s,&m,&d)){        Matrix ban;        memset(ban.mx,0,sizeof(ban.mx));        mm=m*m;        memset(dp,0,sizeof(dp));        for(int i=1;i<=10;i++)dp[i][i]=1;for(int i=1;i<=10;i++){for(int j=1;j<=m&&j<=i;j++){for(int k=j;k>=1&&k>=j-d;k--){dp[j][i]+=dp[k][i-j];dp[j][i]%=MOD;}for(int k=j+1;k<=m&&k<=j+d;k++){dp[j][i]+=dp[k][i-j];dp[j][i]%=MOD;}}}if(s<=10){            ll ans=0;            for(int i=1;i<=m;i++)ans=(ans+dp[i][s])%MOD;            printf("%lld\n",ans);}else {            for(int i=1;i<=m;i++){                for(int j=1;j<=m;j++){                    fcc[getidx(i,j)]=dp[i][j];                }            }            for(int i=1;i<=m;i++){                for(int j=1;j<=m;j++){                    if(i<m){                        ban.mx[getidx(j,i+1)][getidx(j,i)]=1;                    }                    else {                        for(int k=j;k>=1&&k>=j-d;k--){                            ban.mx[getidx(k,i-j+1)][getidx(j,i)]=1;                        }                        for(int k=j+1;k<=m&&k<=j+d;k++){                            ban.mx[getidx(k,i-j+1)][getidx(j,i)]=1;                        }                    }                }            }            ban=power(ban,s-m);            for(int i=1;i<=mm;i++){                ans[i]=0;                for(int j=1;j<=mm;j++){                    ans[i]+=fcc[j]*ban.mx[j][i];                    ans[i]%=MOD;                }            }            ll sum=0;            for(int i=1;i<=m;i++){                sum+=ans[getidx(i,m)];                sum%=MOD;            }            printf("%lld\n",sum);}    }    return 0;}


原创粉丝点击