結果
問題 | No.214 素数サイコロと合成数サイコロ (3-Medium) |
ユーザー | kuuso1 |
提出日時 | 2015-08-11 16:29:49 |
言語 | C#(csc) (csc 3.9.0) |
結果 |
AC
|
実行時間 | 2,776 ms / 3,000 ms |
コード長 | 6,918 bytes |
コンパイル時間 | 942 ms |
コンパイル使用メモリ | 115,972 KB |
実行使用メモリ | 29,236 KB |
最終ジャッジ日時 | 2024-07-18 06:43:46 |
合計ジャッジ時間 | 10,578 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 1,947 ms
28,116 KB |
testcase_01 | AC | 2,621 ms
29,236 KB |
testcase_02 | AC | 2,776 ms
27,148 KB |
コンパイルメッセージ
Microsoft (R) Visual C# Compiler version 3.9.0-6.21124.20 (db94f4cc) Copyright (C) Microsoft Corporation. All rights reserved.
ソースコード
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; class TEST{ static void Main(){ Sol mySol =new Sol(); mySol.Solve(); } } class Sol{ public void Solve(){ uint[] PDice=new uint[]{2,3,5,7,11,13}; uint[] CDice=new uint[]{4,6,8,9,10,12}; uint mod=(uint)1e9+7; // dpP[n][val]:n回の出目でvalになる組み合わせ uint[][] dpP=new uint[P+1][]; for(uint i=0;i<=P;i++){ dpP[i]=new uint[13*P+1]; } dpP[0][0]=1; for(uint i=0;i<PDice.Length;i++){ for(uint j=0;j<P;j++){ for(uint k=0;k<dpP[j].Length;k++){ if(k+PDice[i]>=dpP[j+1].Length)continue; dpP[j+1][k+PDice[i]]+=dpP[j][k]; dpP[j+1][k+PDice[i]]%=mod; } } } //Console.WriteLine(String.Join(" ",dpP[P])); // dpC[n][val]:n回の出目でvalになる組み合わせ uint[][] dpC=new uint[C+1][]; for(uint i=0;i<=C;i++){ dpC[i]=new uint[12*C+1]; } dpC[0][0]=1; for(uint i=0;i<CDice.Length;i++){ for(uint j=0;j<C;j++){ for(uint k=0;k<dpC[j].Length;k++){ if(k+CDice[i]>=dpC[j+1].Length)continue; dpC[j+1][k+CDice[i]]+=dpC[j][k]; dpC[j+1][k+CDice[i]]%=mod; } } } //Console.WriteLine(String.Join(" ",dpC[C])); // P,C個の組み合わせ:1回振って出る出目の組み合わせ uint MaxLen=13*P+12*C; ulong[] Throw=new ulong[MaxLen+1]; for(uint i=0;i<=13*P;i++){ for(uint j=0;j<=12*C;j++){ Throw[i+j]+=dpP[P][i]*dpC[C][j]; Throw[i+j]%=mod; } } //Console.WriteLine(String.Join(" ",Throw)); //Console.WriteLine("MaxLen={0}",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)) ulong[] rel=new ulong[MaxLen]; for(uint i=0;i<MaxLen;i++)rel[i]=Throw[i+1]; Array.Reverse(rel); // 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); var Kitamasa=new ModPolynomial_m(rel,mod); //for(uint i=0;i<30;i++)Console.WriteLine(i+":"+String.Join(" ",Kitamasa.CalcModPolyT(i))+":"+Kitamasa.CalcModPolyT(i).Sum()); ulong[] coef=Kitamasa.CalcModPolyT(N+MaxLen-1); ulong ret=0; for(uint i=0;i<coef.Length;i++){ ret+=1*coef[i]; while(ret>mod)ret-=mod; } Console.WriteLine(ret); } ulong N; uint P,C; public Sol(){ var ss=rsa(); N=ulong.Parse(ss[0]); P=uint.Parse(ss[1]); C=uint.Parse(ss[2]); } static String rs(){return Console.ReadLine();} static uint ri(){return uint.Parse(Console.ReadLine());} static ulong rl(){return ulong.Parse(Console.ReadLine());} static double rd(){return double.Parse(Console.ReadLine());} static String[] rsa(){return Console.ReadLine().Split(' ');} static uint[] ria(){return Array.ConvertAll(Console.ReadLine().Split(' '),e=>uint.Parse(e));} static ulong[] rla(){return Array.ConvertAll(Console.ReadLine().Split(' '),e=>ulong.Parse(e));} static double[] rda(){return Array.ConvertAll(Console.ReadLine().Split(' '),e=>double.Parse(e));} } class ModPolynomial_m{ //Kitamasa method (naive convolution/naive reduction); uint K; ulong[] Rel; ulong mod; public ModPolynomial_m(ulong[] rel,ulong mod_){ // 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); Rel=new ulong[rel.Length]; K=(uint)Rel.Length; for(uint i=0;i<K;i++)Rel[i]=rel[i]; mod=mod_; } public ulong[] Convolution_m(ulong[] a,ulong[] b){ // calc. a*b (convolution) naive uint L=(uint)(a.Length+b.Length-1); ulong[] ret=new ulong[L]; for(uint i=0;i<a.Length;i++){ if(a[i]==0)continue; for(uint j=0;j<b.Length;j++){ if(b[j]==0)continue; ret[i+j]+=a[i]*b[j]; if(ret[i+j]>mod)ret[i+j]%=mod; } } return ret; } public ulong[] Reduction_m(ulong[] a){ // reduce with Relation a(k)=rel[0]*a0+...+rel[k-1]*a(k-1); if(a.Length<=K)return a; uint N=(uint)a.Length; //ulong[] ret0=(ulong[])a.Clone(); ulong[] ret0=new ulong[a.Length]; for(uint i=0;i<a.Length;i++)ret0[i]=a[i]; // ulonger than K part for(uint i=N-1;i>=K;i--){ if(ret0[i]==0)continue; for(uint 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; } } ulong[] ret=new ulong[K]; for(uint i=0;i<K;i++)ret[i]=ret0[i]; return ret; } public ulong[] CalcModPolyT(ulong k){ // calc T^k mod Rel, return the coef. // b7=b(1+2+4)=b1*b2*b4 etc. ulong[] ret=new ulong[]{1};//b0 ulong[] x=new ulong[]{0,1};//b1 while(k>0){ if((k&1)==1){ ret=Reduction_m( Convolution_m( ret,x )); } k>>=1; x=Reduction_m( Convolution_m( x,x )); } return ret; } /* b0:(a0,a1,a2)->a0 b0=(1,0,0); b0:(a1,a2,a3)->a1 b1:(a0,a1,a2)->a1 b1=(0,1,0); b0:(a2,a3,a4)->a2 b1:(a1,a2,a3)->a2 b2:(a0,a1,a2)->a2 b2=(0,0,1); b0:(a3,a4,a5)->a3 b1:(a2,a3,a4)->a3 b2:(a1,a2,a3)->a3 b3:(a0,a1,a2)->a3 b3=(0,0,0,1)=(1,1,1) <=> a3=a2+a1+a0; <=> t^3 mod t^3-t^2-t^1-1 = t^2+t^1+1 b0:(a4,a5,a6)->a4 b1:(a3,a4,a5)->a4 b2:(a2,a3,a4)->a4 b3:(a1,a2,a3)->a4 b4:(a0,a1,a2)->a4 b4=(0.0,0,0,1)=(0,1,1,1)=(1,2,2) <=> a4=a1+a2+a3=a0+2*a1+2*a2 <=> t^4 mod t^3-t^2-t^1-1 == t^3+t^2+t^1 == 2*t^2+2*t^1+1 b(x+y)=b(1+...+1+1+...+1)=b1*...*b1*b1*...*b1=b(1+...+1)*b(1+...+1)=bx*by */ }