結果
問題 | No.213 素数サイコロと合成数サイコロ (3-Easy) |
ユーザー | kuuso1 |
提出日時 | 2015-08-30 13:54:56 |
言語 | C90 (gcc 11.4.0) |
結果 |
AC
|
実行時間 | 21 ms / 3,000 ms |
コード長 | 5,962 bytes |
コンパイル時間 | 183 ms |
コンパイル使用メモリ | 24,448 KB |
実行使用メモリ | 6,944 KB |
最終ジャッジ日時 | 2024-07-18 15:38:00 |
合計ジャッジ時間 | 649 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 12 ms
6,816 KB |
testcase_01 | AC | 21 ms
6,944 KB |
コンパイルメッセージ
main.c: In function ‘main’: main.c:105:9: warning: ignoring return value of ‘scanf’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 105 | scanf("%lld %d %d",&N,&P,&C); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
ソースコード
#include <stdio.h> #include <stdlib.h> #define Long long long int Long dpP[301][4000]; Long dpC[301][4000]; //kitamasa int K; Long Rel[8000]; Long 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; //printf("conv:a.Length=%d,a=",aLen);for(i=0;i<aLen;i++)printf(i==0?"%lld":" %lld",a[i]);puts(""); //printf("conv:b.Length=%d,b=",bLen);for(i=0;i<bLen;i++)printf(i==0?"%lld":" %lld",b[i]);puts(""); 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; } } //printf("--->:r.Length=%d,r=",*abLen);for(i=0;i<*abLen;i++)printf(i==0?"%lld":" %lld",ret[i]);puts(""); return ret; } Long *Reduction_m(Long *a,int aLen,int *retLen){ int i,j; //printf("redu:a.Length=%d,a=",aLen);for(i=0;i<aLen;i++)printf(i==0?"%lld":" %lld",a[i]);puts(""); // reduce with Relation a(k)=rel[0]*a0+...+rel[k-1]*a(k-1); if(aLen<=K){*retLen=aLen;return a;} int N=aLen; //long[] ret0=(long[])a.Clone(); Long *ret0=(Long *)malloc(aLen*sizeof(Long)); 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]; *retLen=K; //printf("--->:r.Length=%d,r=",*retLen);for(i=0;i<*retLen;i++)printf(i==0?"%lld":" %lld",ret[i]);puts(""); return ret; } Long *Kitamasa_CalcModPolyT(Long k,int *len){ int i; 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; int cLen=0; while(k>0){ //printf("k=%lld,retLen=%d,ret=",k,retLen);for(i=0;i<retLen;i++)printf(i==0?"%lld":" %lld",ret[i]);printf("\n"); if((k&1)==1){ Long *retc=Convolution_m( ret,x,retLen,xLen,&cLen ); ret=Reduction_m( retc,cLen,&retLen); } k=(k>>1); Long *xc=Convolution_m( x,x,xLen,xLen,&cLen ); x=Reduction_m( xc,cLen,&xLen); } *len=retLen; //printf("retLen=%d,ret=",retLen);for(i=0;i<retLen;i++)printf(i==0?"%lld":" %lld",ret[i]);printf("\n"); 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=(Long)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; } } } //for(i=0;i<13*P+1;i++)printf(i==0?"%lld":" %lld",dpP[P][i]);printf("\n"); // 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; } } } //for(i=0;i<12*C+1;i++)printf(i==0?"%lld":" %lld",dpC[C][i]);printf("\n"); // P,C個の組み合わせ:1回振って出る出目の組み合わせ int MaxLen=13*P+12*C; Long *Throw=(Long *)malloc((MaxLen+1)*sizeof(Long)); for(i=0;i<MaxLen+1;i++)Throw[i]=0; 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; } } //for(i=0;i<MaxLen+1;i++)printf(i==0?"%lld":" %lld",Throw[i]);printf("\n"); //printf("MaxLen=%d\n",MaxLen); // 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; }