#include #include #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;imod)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=K;i--){ if(ret0[i]==0)continue; for(j=0;jmod)ret0[i-K+j]%=mod; } } Long *ret=(Long *)malloc(K*sizeof(Long)); for(i=0;i: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>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=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=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=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;imod)ret-=mod; } printf("%lld\n",ret); return 0; }