hdu 3369 Robot

題目: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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章