結果
問題 | No.214 素数サイコロと合成数サイコロ (3-Medium) |
ユーザー | kuuso1 |
提出日時 | 2015-08-30 12:53:52 |
言語 | C90 (gcc 11.4.0) |
結果 |
RE
|
実行時間 | - |
コード長 | 4,786 bytes |
コンパイル時間 | 327 ms |
コンパイル使用メモリ | 24,832 KB |
実行使用メモリ | 5,376 KB |
最終ジャッジ日時 | 2024-07-18 15:37:43 |
合計ジャッジ時間 | 1,665 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | RE | - |
testcase_01 | RE | - |
testcase_02 | RE | - |
コンパイルメッセージ
main.c: In function ‘main’: main.c:94:9: warning: ignoring return value of ‘scanf’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 94 | scanf("%lld %d %d",&N,&P,&C); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
ソースコード
#include <stdio.h> #include <stdlib.h> #define Long long long int int dpP[301][4000]; int dpC[301][4000]; //kitamasa int K; Long Rel[8000]; int mod; void ModPolynomial_m_init(Long rel[],int mod_,int k_){ // usage: ak=rel[0]*a0+...+rel[k-1]*a(k-1); // T^k=rel[0]*1+rel[1]*T^1+...+rel[k-1]*T^(k-1); int i; K=k_; for(i=0;i<K;i++)Rel[i]=rel[i]; mod=mod_; } Long *Convolution_m(Long a[],Long b[],int *aLen,int *bLen,int *abLen){ // calc. a*b (convolution) naive int L=*aLen+*bLen-1; *abLen=L; int i,j; Long *ret=(Long *)malloc(L*sizeof(Long)); for(i=0;i<*aLen;i++){ if(a[i]==0)continue; for(j=0;j<*bLen;j++){ if(b[j]==0)continue; ret[i+j]+=a[i]*b[j]; if(ret[i+j]>mod)ret[i+j]%=mod; } } return ret; } Long *Reduction_m(Long a[],int *aLen){ // reduce with Relation a(k)=rel[0]*a0+...+rel[k-1]*a(k-1); if(*aLen<=K)return a; int N=*aLen; int i,j; //long[] ret0=(long[])a.Clone(); Long ret0[*aLen]; for(i=0;i<*aLen;i++)ret0[i]=a[i]; // longer than K part for(i=N-1;i>=K;i--){ if(ret0[i]==0)continue; for(j=0;j<K;j++){ if(Rel[j]==0)continue; ret0[i-K+j]+=ret0[i]*Rel[j]; if(ret0[i-K+j]>mod)ret0[i-K+j]%=mod; } } Long *ret=(Long *)malloc(K*sizeof(Long)); for(i=0;i<K;i++)ret[i]=ret0[i]; *aLen=K; return ret; } Long *Kitamasa_CalcModPolyT(Long k,int *len){ int retLen=1; Long *ret; ret=(Long *)malloc(retLen*sizeof(Long)); ret[0]=1; int xLen=2; Long *x; x=(Long *)malloc(xLen*sizeof(Long)); x[0]=0;x[1]=1; while(k>0){ if(k&1){ ret=Reduction_m( Convolution_m( ret,x,&retLen,&xLen,&retLen ),&retLen); } k=(k>>1); x=Reduction_m( Convolution_m( x,x,&xLen,&xLen,&xLen ),&xLen); } *len=retLen; return ret; } int main(){ Long N; int P,C; int i,j,k; scanf("%lld %d %d",&N,&P,&C); int PDice[6]={2,3,5,7,11,13}; int CDice[6]={4,6,8,9,10,12}; mod=(int)1e9+7; // dpP[n][val]:n回の出目でvalになる組み合わせ dpP[0][0]=1; for(i=0;i<6;i++){ for(j=0;j<P;j++){ for(k=0;k<13*P+1;k++){ if(k+PDice[i]>=13*P+1)continue; dpP[j+1][k+PDice[i]]+=dpP[j][k]; dpP[j+1][k+PDice[i]]%=mod; } } } // dpC[n][val]:n回の出目でvalになる組み合わせ dpC[0][0]=1; for(i=0;i<6;i++){ for(j=0;j<C;j++){ for(k=0;k<12*C+1;k++){ if(k+CDice[i]>=12*C+1)continue; dpC[j+1][k+CDice[i]]+=dpC[j][k]; dpC[j+1][k+CDice[i]]%=mod; } } } // P,C個の組み合わせ:1回振って出る出目の組み合わせ int MaxLen=13*P+12*C; Long Throw[MaxLen+1]; for(i=0;i<=13*P;i++){ for(j=0;j<=12*C;j++){ Throw[i+j]+=dpP[P][i]*dpC[C][j]; Throw[i+j]%=mod; } } // C[k]をk番目のマスに来る組み合わせとして、0番目のマスからN-1番目のマスまで順次サイコロを振っていく様子を考える。 // ・kマスからk+tマスに動く組み合わせは C[k]*Throw[t] だけあるので // kマスでサイコロを振ると、C[k+j] (j=1,2,…,13*P+12*C)にC[k]*Throw[j]だけ足されていく。 // ・C[0]==1 // // (簡潔化のため出目の最大値=3、Throw[1]=a,Throw[2]=b,Throw[3]=c とし、N=5とすると // // Turn 0 1 2 3 4 5 6 7 (マス) // 0 C[*] 1(=C0) // 1 C[*] C0*a C0*b C0*c // (=C1) // 2 C[*] C0*b+C1*a C0*c+C1*b C1*c // (=C2) // 3 C[*] C0*c+C1*b+C2*a C1*c+C2*b C2*c // (=C3) // 4 C[*] C1*c+C2*b+C3*a C2*c+C3*b C3*c // (=C4) // 5 C[*] C2*c+C3*b+C4*a C3*c+C4*b C4*c // // この時点で全ての場合においてN>=5にゴールしているので、ここで和を取る。(C2*c+C3*b+C4*a + C3*c+C4*b + C4*c) // // ・ここで係数だけみると、 多項式 T^7 を 多項式 T^3-(a*T^2+b*T^1+c*T^0) で筆算で割り算しているのと同じという事がわかる。 // (最後に余りの係数の総和をとる) // ・ということで、元の問題は 多項式 T^(N+(出目の最大値)-1) を 多項式 ΣThrow[k]*T^k で割って、余りを求めればよい。 // kitamasa(O(d^2 Log N)) Long rel[MaxLen]; for(i=0;i<MaxLen;i++)rel[i]=Throw[MaxLen-i]; // usage:ak=rel[0]*a0+...+rel[k-1]*a(k-1); // T^k=rel[0]*1+rel[1]*T^1+...+rel[k-1]*T^(k-1); ModPolynomial_m_init(rel,mod,MaxLen); Long *coef; int coefLen=0; coef=Kitamasa_CalcModPolyT(N+MaxLen-1,&coefLen); Long ret=0; for(i=0;i<coefLen;i++){ ret+=1*coef[i]; while(ret>mod)ret-=mod; } printf("%lld\n",ret); return 0; }