結果
問題 | No.214 素数サイコロと合成数サイコロ (3-Medium) |
ユーザー | 37zigen |
提出日時 | 2016-08-02 01:45:50 |
言語 | Java21 (openjdk 21) |
結果 |
MLE
|
実行時間 | - |
コード長 | 5,165 bytes |
コンパイル時間 | 2,474 ms |
コンパイル使用メモリ | 79,580 KB |
実行使用メモリ | 158,288 KB |
最終ジャッジ日時 | 2024-11-06 21:48:16 |
合計ジャッジ時間 | 10,834 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | MLE | - |
testcase_01 | -- | - |
testcase_02 | -- | - |
ソースコード
import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.util.Arrays; import java.util.Scanner; public class Main { static InputStream is; static PrintWriter out; static String INPUT = ""; public static void main(String[] args) throws Exception { is = INPUT.isEmpty() ? System.in : new ByteArrayInputStream(INPUT.getBytes()); out = new PrintWriter(System.out); solver(); out.flush(); } static long nl() { try { long num = 0; boolean minus = false; while ((num = is.read()) != -1 && !((num >= '0' && num <= '9') || num == '-')) ; if (num == '-') { num = 0; minus = true; } else { num -= '0'; } while (true) { int b = is.read(); if (b >= '0' && b <= '9') { num = num * 10 + (b - '0'); } else { return minus ? -num : num; } } } catch (IOException e) { } return -1; } static char nc() { try { int b = skip(); if (b == -1) return 0; return (char) b; } catch (IOException e) { } return 0; } static double nd() { try { return Double.parseDouble(ns()); } catch (Exception e) { } return 0; } static String ns() { try { int b = skip(); StringBuilder sb = new StringBuilder(); if (b == -1) return ""; sb.append((char) b); while (true) { b = is.read(); if (b == -1) return sb.toString(); if (b <= ' ') return sb.toString(); sb.append((char) b); } } catch (IOException e) { } return ""; } public static char[] ns(int n) { char[] buf = new char[n]; try { int b = skip(), p = 0; if (b == -1) return null; buf[p++] = (char) b; while (p < n) { b = is.read(); if (b == -1 || b <= ' ') break; buf[p++] = (char) b; } return Arrays.copyOf(buf, p); } catch (IOException e) { } return null; } public static byte[] nse(int n) { byte[] buf = new byte[n]; try { int b = skip(); if (b == -1) return null; is.read(buf); return buf; } catch (IOException e) { } return null; } static int skip() throws IOException { int b; while ((b = is.read()) != -1 && !(b >= 33 && b <= 126)) ; return b; } static boolean eof() { try { is.mark(1000); int b = skip(); is.reset(); return b == -1; } catch (IOException e) { return true; } } static int ni() { try { int num = 0; boolean minus = false; while ((num = is.read()) != -1 && !((num >= '0' && num <= '9') || num == '-')) ; if (num == '-') { num = 0; minus = true; } else { num -= '0'; } while (true) { int b = is.read(); if (b >= '0' && b <= '9') { num = num * 10 + (b - '0'); } else { return minus ? -num : num; } } } catch (IOException e) { } return -1; } static long mod =1_000_000_000+7; static void solver(){ long n=nl(); int p=ni(); int c=ni(); //まず、さいころをP+C個振って和がK個になるパターン数をDPで数える。 long[][] k=new long[p+c+1][13*(p+c)+1]; k[0][0]=1; int[] prime={2,3,5,7,11,13}; int[] composite={4,6,8,9,10,12}; for(int l=0;l<6;l++){ for(int i=0;i<p;i++){ for(int j=0;j<k[0].length;j++){ if(k[i][j]>0){ k[i+1][j+prime[l]]+=k[i][j]; k[i+1][j+prime[l]]%=mod; } } } } for(int l=0;l<6;l++){ for(int i=0;i<c;i++){ for(int j=0;j<k[0].length;j++){ if(k[p+i][j]>0){ k[p+i+1][j+composite[l]]+=k[p+i][j]; k[p+i+1][j+composite[l]]%=mod; } } } } int n_k=k[0].length-1; long[][] A=new long[n_k][n_k]; for(int i=0;i<n_k-1;i++)A[i][i+1]=1; for(int i=0;i<n_k;i++){ A[n_k-1][i]=k[p+c][n_k-i]; } //a[1]~a[n_k]を用意 long[][] a=new long[n_k][1]; for(int i=1;i<k[0].length;i++){ //iはサイコロの目の和 for(int j=0;j>-k[0].length;j--){ //-jから出発した場合 if(i+j>=1){ a[i+j-1][0]+=k[p+c][i]; a[i+j-1][0]%=mod; } } } for(int i=0;i<a.length;i++){ for(int j=i-1;j>=0;j--){ a[i][0]+=(k[p+c][i-j]*a[j][0])%mod; a[i][0]%=mod; } } long[] e=new long[a.length]; for(int i=0;i<k[0].length-1;i++)e[i]=k[p+c][i+1]; long[] aa=new long[a.length]; for(int i=0;i<aa.length;i++)aa[i]=a[i][0]; long ans=solve(n,e,aa,mod); out.println(ans); } //a[n]=e[0]a[n-1]+e[1]a[n-2]+...+e[K-1]a[n-K]: //a[i]=第i+1項目の値(初期条件) //第N項目を求める。 static long solve(long N,long[] e,long[] a,long mod){ int K=e.length; long[] x=new long[K]; long[] y=new long[K]; x[1]=1; y[0]=1; for(long n=N-1;n>0;n>>=1,x=mul(x,x,e,mod)){ if((n&1)==1)y=mul(y,x,e,mod); } long ans=0; for(int i=0;i<K;i++){ ans=(ans+(long)y[i]*a[i])%mod; } return ans; } static long[] mul(long[] a,long[] b,long[] e,long mod){ int K=e.length; int i,j; long[] c=new long[2*K]; for(i=0;i<K;i++){ for(j=0;j<K;j++){ c[i+j]=(c[i+j]+a[i]*b[j])%mod; } } for(i=2*K-1;i>=K;i--){ for(j=1;j<=K;j++){ c[i-j]=(c[i-j]+e[j-1]*c[i])%mod; } } long[] d=new long[K]; for(i=0;i<K;i++)d[i]=c[i]; return d; } }