hdu 3369 Robot

来源:互联网 发布:公民网络身份识别系统 编辑:程序博客网 时间:2024/06/04 18:39

题目:hdu 3369 Robot

题意:告诉你从周几开始,到第n天总的学会单词的个数,其中第i天学会i^k个单词,周末学会单词为0

思路:给的k的范围比较小,n的范围比较大

开始想的是,枚举k,但是这样对于n并没有影响

所以,我们要处理的应该是,i^k+(i+7)^k+(i+14)^k+....(i+7*j)^k这样的一个通式

由于k的范围比较小,展开成k+1项二项式表示之后可以构造矩阵,然后转化成二分求矩阵和

Wa了好几遍,因为写法写搓了,多判断从周末开始到下周周末的周末的情况(周日算到下周六,多加了个下周六的)


暂时提交里面,时间应该属我最长吧,没办法,代码写的搓。。。。唉~


#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <iostream>using namespace std;typedef long long LL;const LL mod=1000000007;LL C[13][13];int K;struct Matrix{    LL m[13][13];}E,D[8],O;LL Pow(LL a,LL b){    LL ans=1;    while(b){        if(b&1) b--,ans=(ans*a)%mod;        else b/=2,a=(a*a)%mod;    }    return ans;}void init(){    for(int i=1;i<=12;i++){        for(int j=1;j<=12;j++)            E.m[i][j]=(i==j);    }    memset(C,0,sizeof(C));    for(int i=1;i<=12;i++){        C[i][0]=C[i][i]=1;        C[i][1]=i;        for(int j=2;j<i;j++)            C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;    }    C[0][0]=1;    for(int i=1;i<=12;i++){        for(int j=0;j<=i;j++)            C[i][j]=(C[i][j]*Pow(7,j))%mod;    }    memset(O.m,0,sizeof(O.m));    for(int i=1;i<=K;i++){        for(int j=i;j<=K;j++){            O.m[i][j]=C[K-i][j-i];        }    }    for(int i=1;i<=7;i++){        //memset(D[i].m,0,sizeof(D[i].m));        D[i].m[K][1]=1;        for(int j=K-1;j>=1;j--)            D[i].m[j][1]=(D[i].m[j+1][1]*i)%mod;    }}Matrix Multi(Matrix A,Matrix B){    Matrix ans;    for(int i=1;i<=K;i++){        for(int j=1;j<=K;j++){            ans.m[i][j]=0;            for(int k=1;k<=K;k++)                ans.m[i][j]=(ans.m[i][j]+(A.m[i][k]*B.m[k][j])%mod)%mod;        }    }    return ans;}Matrix Pow(Matrix A,LL k){    Matrix ans=E;    while(k){        if(k&1) k--,ans=Multi(ans,A);        else k/=2,A=Multi(A,A);    }    return ans;}Matrix Add(Matrix A,Matrix B){    Matrix ans;    for(int i=1;i<=K;i++){        for(int j=1;j<=K;j++)            ans.m[i][j]=(A.m[i][j]+B.m[i][j])%mod;    }    return ans;}Matrix Sum(Matrix A,LL k){    if(k==0) return E;    if(k==1) return Add(A,E);    if(k&1) return Multi(Sum(A,k/2),Add(E,Pow(A,(k+1)/2)));    else return Add(Multi(Sum(A,(k-1)/2),Add(E,Pow(A,k/2))),Pow(A,k));}LL get(LL x,LL n){    LL ans=(Multi(Sum(O,n),D[x])).m[1][1]%mod;    return ans;}void Print(Matrix A){    for(int i=1;i<=K;i++){        for(int j=1;j<=K;j++)            cout<<A.m[i][j]<<" ";        cout<<endl;    }}char s[7][10]={"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};int main(){    int T;    scanf("%d",&T);    char str[10];    for(int cas=1;cas<=T;cas++){        scanf("%s",&str);        int st=1;        for(;st<=7;st++){            if(strcmp(s[st-1],str)==0)    break;        }        LL n,k,ans=0;        scanf("%I64d%I64d",&n,&k);        K=k+1;        init();        //Print(O);        int i=st;        int x=0;        for(;i!=st+7;i++){            x++;            if(i==6 || i==7 || i==6+7 || i==7+7) continue;            if( n-x<0) break;            /*cout<<x<<":"<<(n-x)/7<<" "<<endl;            cout<<get(x,(n-x)/7)<<endl;*/            ans=(ans+get(x,(n-x)/7))%mod;        }        //cout<<"Case "<<cas<<": "<<ans<<endl;        printf("Case %d: %I64d\n",cas,ans);    }    return 0;}


0 0
原创粉丝点击