結果
| 問題 |
No.214 素数サイコロと合成数サイコロ (3-Medium)
|
| コンテスト | |
| ユーザー |
kuuso1
|
| 提出日時 | 2015-08-30 12:53:52 |
| 言語 | C90 (gcc 12.3.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 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | RE * 3 |
コンパイルメッセージ
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;
}
kuuso1