2011年8月25日木曜日

CodeChef August Cook-off 2011

CodeChef August Cook-off 2011(8/22 1:00~3:30)

■Open the Dragon Scroll

問題

A,B,Nが与えられる.
(2進数で)A,BのビットをNビットに収まる範囲で自由に並び替える.
A xor B = Cの最大値を求めよ.

解法

A,Bにおける1のビットの数を|A|,|B|とする.

1.|A|+|B|≦N

この時は,以下のようにビットを並び替えれば最大値になる.
A→11…1100…0000…00
B→00…0011…1100…00
C→11…1111…1100…00
(1が|A|+|B|個,0がN-(|A|+|B|)個)

2.|A|+|B|>N

xorをとると,どうしてもどこかでAの1とBの1が相殺して0になってしまう.
そのため,ビットを下のように並びかえる.
A→11…1100…0011…11
B→00…0011…1111‥11
この時,1 xor 1 = 0で相殺されてしまう1(右端の1のこと)の個数をXとすれば,
|A|+|B|-X=N
∴X=|A|+|B|-N
C→11…1111…1100…00
(1が2|N|-(|A|+|B|)個,0が|A|+|B|-N個)
  1. import java.util.*;  
  2. import java.lang.*;  
  3. import java.math.*;  
  4. import java.io.*;  
  5.   
  6. import static java.lang.Math.*;  
  7. import static java.util.Arrays.*;  
  8.   
  9. public class Main{  
  10.     Scanner sc=new Scanner(System.in);  
  11.   
  12.     int INF=1<<28;  
  13.     double EPS=1e-9;  
  14.   
  15.     int t, n, a, b;  
  16.   
  17.     void run(){  
  18.         t=sc.nextInt();  
  19.         for(int i=0; i<t; i++){  
  20.             n=sc.nextInt();  
  21.             a=sc.nextInt();  
  22.             b=sc.nextInt();  
  23.             solve();  
  24.         }  
  25.     }  
  26.   
  27.     void solve(){  
  28.         int ans=0;  
  29.         int bitA=Integer.bitCount(a);  
  30.         int bitB=Integer.bitCount(b);  
  31.         if(bitA+bitB<=n){  
  32.             for(int i=0; i<n; i++){  
  33.                 ans<<=1;  
  34.                 if(i<bitA+bitB){  
  35.                     ans++;  
  36.                 }  
  37.             }  
  38.         }else{  
  39.             for(int i=0; i<n; i++){  
  40.                 ans<<=1;  
  41.                 if(i<2*n-(bitA+bitB)){  
  42.                     ans++;  
  43.                 }  
  44.             }  
  45.         }  
  46.         println(ans+"");  
  47.     }  
  48.   
  49.     void println(String s){  
  50.         System.out.println(s);  
  51.     }  
  52.   
  53.     void print(String s){  
  54.         System.out.print(s);  
  55.     }  
  56.   
  57.     void debug(Object... os){  
  58.         System.err.println(Arrays.deepToString(os));  
  59.     }  
  60.   
  61.     public static void main(String[] args){  
  62.         new Main().run();  
  63.     }  
  64. }  

■Vote for the Noodle Soup

問題

ある投票システムがある.
投票する際のスコアは+1/-1で,一度投票したら無効には出来ない.
スコアを見るためには,上記のスコアで投票する必要がある.
Poは,(+1/-1に)複数回投票し,スコアを記録した.
得られたスコアから,(Poを除いた)総投票者の最小数を求めよ.

解法

得られたスコアをscore[i]と表す.
Poが入れたポイント(vote[i]とする)は計算の邪魔なので,score[i]から予め引いておく.
score[0]~score[n-1]まで逐一見ていく.
i番目まで見たときの投票者数の最小値をnUsers[i]とする.
明らかなのは,
nUsers[0]=0
nUsers[i+1]=max(nUsers[i], |score[i+1]|)
ということ.投票者数は,最低でもスコアの絶対値だけ必要.
次に,nUsers[i]+score[i+1]が奇数だった場合は,
nUsers[i+1]=nUsers[i]+1
とする必要がある.何故なら,
nUsers[i]が偶数/奇数⇔score[i]が偶数/奇数
だから.そして,投票者数は減らないから,+1する.
  1. import java.util.*;  
  2. import java.lang.*;  
  3. import java.math.*;  
  4. import java.io.*;  
  5.   
  6. import static java.lang.Math.*;  
  7. import static java.util.Arrays.*;  
  8.   
  9. public class Main{  
  10.     Scanner sc=new Scanner(System.in);  
  11.   
  12.     int INF=1<<28;  
  13.     double EPS=1e-9;  
  14.   
  15.     int n;  
  16.     int[] vote, ps;  
  17.   
  18.     void run(){  
  19.         for(;;){  
  20.             n=sc.nextInt();  
  21.             if(n==0){  
  22.                 break;  
  23.             }  
  24.             vote=new int[n];  
  25.             ps=new int[n];  
  26.             for(int i=0; i<n; i++){  
  27.                 vote[i]=sc.next().equals("P")?+1:-1;  
  28.                 ps[i]=sc.nextInt()-vote[i];  
  29.             }  
  30.             solve();  
  31.         }  
  32.     }  
  33.   
  34.     void solve(){  
  35.         int min=0;  
  36.         for(int i=0; i<n; i++){  
  37.             if(abs(ps[i]+min)%2==1){  
  38.                 min++;  
  39.             }  
  40.             min=max(min, abs(ps[i]));  
  41.         }  
  42.         println(min+"");  
  43.     }  
  44.   
  45.     void println(String s){  
  46.         System.out.println(s);  
  47.     }  
  48.   
  49.     void print(String s){  
  50.         System.out.print(s);  
  51.     }  
  52.   
  53.     void debug(Object... os){  
  54.         System.err.println(Arrays.deepToString(os));  
  55.     }  
  56.   
  57.     public static void main(String[] args){  
  58.         new Main().run();  
  59.     }  
  60. }  

■Result

o-o--
実に不本意な結果….

2011年8月10日水曜日

京都大学プログラミングコンテスト KUPC 2011

京都大学プログラミングコンテスト KUPC 2011(8/6 13:00~18:00)

久しぶりに,非定期コンテストに参加.

■A KUPC

文字ごとの出現回数をカウントして,
min(count['K'], count['U'], count['P'], count['C'])
が答え.
  1. import java.util.*;  
  2. import java.lang.*;  
  3. import java.math.*;  
  4. import java.io.*;  
  5. import static java.lang.Math.*;  
  6. import static java.util.Arrays.*;  
  7.   
  8. public class Main{  
  9.     Scanner sc=new Scanner(System.in);  
  10.     int INF=1<<28;  
  11.     double EPS=1e-12;  
  12.   
  13.     void run(){  
  14.         String s=sc.next();  
  15.         int[] count=new int[256];  
  16.         for(char c : s.toCharArray()){  
  17.             count[c]++;  
  18.         }  
  19.         int ans=min(count['K'], min(count['U'], min(count['P'], count['C'])));  
  20.         println(ans+"");  
  21.     }  
  22.   
  23.     void debug(Object... os){  
  24.         System.err.println(Arrays.deepToString(os));  
  25.     }  
  26.   
  27.     void print(String s){  
  28.         System.out.print(s);  
  29.     }  
  30.   
  31.     void println(String s){  
  32.         System.out.println(s);  
  33.     }  
  34.   
  35.     public static void main(String[] args){  
  36.         // System.setOut(new PrintStream(new BufferedOutputStream(System.out)));  
  37.         new Main().run();  
  38.     }  
  39. }  

■B 蝉

典型的なDP.
dp[y][x] := (x,y)に到達までに出会う蝉の数の最小値
右か下にしかいけないので,(x,y)の左と上を見ればdp[y][x]を決定できる.
  1. import java.util.*;  
  2. import java.lang.*;  
  3. import java.math.*;  
  4. import java.io.*;  
  5. import static java.lang.Math.*;  
  6. import static java.util.Arrays.*;  
  7.   
  8. public class Main{  
  9.     Scanner sc=new Scanner(System.in);  
  10.     int INF=1<<28;  
  11.     double EPS=1e-12;  
  12.   
  13.     int n, m;  
  14.     int[][] a;  
  15.   
  16.     void run(){  
  17.         n=sc.nextInt();  
  18.         m=sc.nextInt();  
  19.         a=new int[n][m];  
  20.         for(int j=0; j<n; j++){  
  21.             String s=sc.next();  
  22.             for(int i=0; i<m; i++){  
  23.                 a[j][i]=s.charAt(i)-'0';  
  24.             }  
  25.         }  
  26.   
  27.         int[][] dp=new int[n][m];  
  28.         for(int j=0; j<n; j++){  
  29.             fill(dp[j], INF);  
  30.         }  
  31.         dp[0][0]=0;  
  32.         for(int j=0; j<n; j++){  
  33.             for(int i=0; i<m; i++){  
  34.                 if(j>0){  
  35.                     dp[j][i]=min(dp[j][i], dp[j-1][i]+a[j][i]);  
  36.                 }  
  37.                 if(i>0){  
  38.                     dp[j][i]=min(dp[j][i], dp[j][i-1]+a[j][i]);  
  39.                 }  
  40.             }  
  41.         }  
  42.         println(dp[n-1][m-1]+"");  
  43.     }  
  44.   
  45.     void debug(Object... os){  
  46.         System.err.println(Arrays.deepToString(os));  
  47.     }  
  48.   
  49.     void print(String s){  
  50.         System.out.print(s);  
  51.     }  
  52.   
  53.     void println(String s){  
  54.         System.out.println(s);  
  55.     }  
  56.   
  57.     public static void main(String[] args){  
  58.         // System.setOut(new PrintStream(new BufferedOutputStream(System.out)));  
  59.         new Main().run();  
  60.     }  
  61. }  

■C しりとり

'xa'と尋ね続ければ,その内,'a'で始まる文字列が無くなることを利用する.
途中で,不正な返答が来た時の処理等を忘れてWAを食らいまくる.
  1. package c;  
  2.   
  3. import java.util.*;  
  4. import java.lang.*;  
  5. import java.math.*;  
  6. import java.io.*;  
  7. import static java.lang.Math.*;  
  8. import static java.util.Arrays.*;  
  9.   
  10. public class Main{  
  11.     Scanner sc=new Scanner(System.in);  
  12.     int INF=1<<28;  
  13.     double EPS=1e-12;  
  14.   
  15.     void run(){  
  16.         TreeSet<string> set=new TreeSet<string>();  
  17.         println("?a");  
  18.         System.out.flush();  
  19.         set.add("a");  
  20.         String next="";  
  21.         char ch='a';  
  22.         for(; sc.hasNext();){  
  23.             String s=sc.next();  
  24.             boolean out=false;  
  25.             out|=s.charAt(0)!='a';  
  26.             out|=set.contains(s);  
  27.             if(out){  
  28.                 println("!OUT");  
  29.                 break;  
  30.             }  
  31.             set.add(s);  
  32.             println("?"+s.charAt(s.length()-1)+next+ch+"a");  
  33.             if(ch++=='z'){  
  34.                 next+='z';  
  35.                 ch='a';  
  36.             }  
  37.             System.out.flush();  
  38.         }  
  39.     }  
  40.   
  41.     void debug(Object... os){  
  42.         System.err.println(Arrays.deepToString(os));  
  43.     }  
  44.   
  45.     void print(String s){  
  46.         System.out.print(s);  
  47.     }  
  48.   
  49.     void println(String s){  
  50.         System.out.println(s);  
  51.     }  
  52.   
  53.     public static void main(String[] args){  
  54.         // System.setOut(new PrintStream(new BufferedOutputStream(System.out)));  
  55.         new Main().run();  
  56.     }  
  57. }</string></string>  

■D 列の構成

ずっとやり方を考えていたが,DFS+適当な枝刈りで通ってしまった. 想定解法は乱択アルゴリズムという珍しい問題.
  1. import java.util.*;  
  2. import java.lang.*;  
  3. import java.math.*;  
  4. import java.io.*;  
  5. import static java.lang.Math.*;  
  6. import static java.util.Arrays.*;  
  7.   
  8. public class Main{  
  9.     Scanner sc=new Scanner(System.in);  
  10.     int INF=1<<28;  
  11.     double EPS=1e-12;  
  12.   
  13.     int n, k;  
  14.     int[][] a, sum;  
  15.     int[] count, seq;  
  16.     boolean[] brank;  
  17.     boolean end=false;  
  18.   
  19.     void run(){  
  20.         n=sc.nextInt();  
  21.         k=sc.nextInt();  
  22.         a=new int[k][n];  
  23.         brank=new boolean[n];  
  24.         sum=new int[k][n+1];  
  25.         fill(brank, true);  
  26.         for(int j=0; j<k; j++){  
  27.             for(int i=0; i<n/2; i++){  
  28.                 int k=sc.nextInt();  
  29.                 a[j][k-1]=1;  
  30.                 brank[k-1]=false;  
  31.             }  
  32.             for(int i=0; i<n; i++){  
  33.                 sum[j][i+1]=sum[j][i]+a[j][i];  
  34.             }  
  35.         }  
  36.         count=new int[k];  
  37.         seq=new int[n];  
  38.         rec(0);  
  39.     }  
  40.   
  41.     void rec(int x){  
  42.         if(end){  
  43.             return;  
  44.         }  
  45.   
  46.         // 枝刈り  
  47.         for(int j=0; j<k; j++){  
  48.             int rem=sum[j][n]-sum[j][x];  
  49.             if(count[j]+rem<n/8){  
  50.                 return;  
  51.             }  
  52.             if(count[j]>3*n/8){  
  53.                 return;  
  54.             }  
  55.         }  
  56.   
  57.         if(x==n){  
  58.             end=true;  
  59.             for(int i=0; i<n; i++){  
  60.                 print(seq[i]+"");  
  61.             }  
  62.             println("");  
  63.             return;  
  64.         }  
  65.   
  66.         if(brank[x]){  
  67.             rec(x+1);  
  68.             return;  
  69.         }  
  70.   
  71.         seq[x]=0;  
  72.         rec(x+1);  
  73.   
  74.         seq[x]=1;  
  75.         for(int j=0; j<k; j++){  
  76.             count[j]+=a[j][x];  
  77.         }  
  78.         rec(x+1);  
  79.         for(int j=0; j<k; j++){  
  80.             count[j]-=a[j][x];  
  81.         }  
  82.   
  83.     }  
  84.   
  85.     void debug(Object... os){  
  86.         System.err.println(Arrays.deepToString(os));  
  87.     }  
  88.   
  89.     void print(String s){  
  90.         System.out.print(s);  
  91.     }  
  92.   
  93.     void println(String s){  
  94.         System.out.println(s);  
  95.     }  
  96.   
  97.     public static void main(String[] args){  
  98.         // System.setOut(new PrintStream(new BufferedOutputStream(System.out)));  
  99.         new Main().run();  
  100.     }  
  101. }  

■E Fox Number

Fox Numberでない数を列挙する. n=p1p22は条件を満たさないことを使う (p1,p2は素数).
kn∈[A-B, A+B]となる最小のkを以下で求める.
k=max([(A-B)/n], 1)
そして,kn∈[A-B, A+B]である間,kをインクリメント.
ここで,kn=p11+rkp22+skm と表わすことが出来る.
1+rk < 2+sk
ならば,knはFox Numberでないので,
isNotFoxNumber[kn]=true
これを妥当な範囲内の素数全てについて行う.
  1. import java.util.*;  
  2. import java.util.Map.Entry;  
  3. import java.lang.*;  
  4. import java.math.*;  
  5. import java.io.*;  
  6. import static java.lang.Math.*;  
  7. import static java.util.Arrays.*;  
  8.   
  9. public class Main{  
  10.     Scanner sc=new Scanner(System.in);  
  11.     int INF=1<<28;  
  12.     double EPS=1e-12;  
  13.   
  14.     long a;  
  15.     int b;  
  16.     int p, m;  
  17.     int[] prime;  
  18.     boolean[] isPrime;  
  19.     boolean[] fox;  
  20.   
  21.     void run(){  
  22.         a=sc.nextLong();  
  23.         b=sc.nextInt();  
  24.   
  25.         fox=new boolean[2*b+1];  
  26.         fill(fox, true);  
  27.           
  28.         for(int i=0;i<2*b+1;i++){  
  29.             if(i-b+a<2){  
  30.                 fox[i]=false;  
  31.             }  
  32.         }  
  33.   
  34.         m=(int)sqrt(a+b)+10;  
  35.         p=0;  
  36.         prime=new int[m];  
  37.         isPrime=new boolean[m+1];  
  38.         Arrays.fill(isPrime, true);  
  39.         isPrime[0]=isPrime[1]=false;  
  40.         for(int i=2; i<=m; i++){  
  41.             if(isPrime[i]){  
  42.                 prime[p++]=i;  
  43.                 for(int j=2*i; j<=m; j+=i)  
  44.                     isPrime[j]=false;  
  45.             }  
  46.         }  
  47.   
  48.         int e1=1, e2=2;  
  49.         for(int p2=0; p2<p; p2++){  
  50.             long n2=(long)prime[p2]*prime[p2];  
  51.             if(n2>a+b){  
  52.                 break;  
  53.             }  
  54.             for(int p1=0; p1<p2; p1++){  
  55.                 long n1=prime[p1];  
  56.                 long n=n1*n2;  
  57.                 if(n<0){  
  58.                     debug(n);  
  59.                 }  
  60.                 if(n>a+b){  
  61.                     break;  
  62.                 }  
  63.   
  64.                 int c=0;  
  65.                 for(long k=max((a-b)/n, 1); k*n<=a+b; k++){  
  66.                     c++;  
  67.                     int pc1=0;  
  68.                     for(long i=k; i%prime[p1]==0; i/=prime[p1]){  
  69.                         pc1++;  
  70.                     }  
  71.                     int pc2=0;  
  72.                     for(long i=k; i%prime[p2]==0; i/=prime[p2]){  
  73.                         pc2++;  
  74.                     }  
  75.   
  76.                     if(e1+pc1<e2+pc2){  
  77.                         if(k*n>=a-b){  
  78.                             fox[(int)(k*n-a+b)]=false;  
  79.                         }  
  80.                     }  
  81.                 }  
  82.             }  
  83.         }  
  84.   
  85.         int c=0;  
  86.         for(int i=0; i<2*b+1; i++){  
  87.             if(fox[i]){  
  88.                 c++;  
  89.             }  
  90.         }  
  91.   
  92.         println(c+"");  
  93.     }  
  94.   
  95.     void debug(Object... os){  
  96.         System.err.println(Arrays.deepToString(os));  
  97.     }  
  98.   
  99.     void print(String s){  
  100.         System.out.print(s);  
  101.     }  
  102.   
  103.     void println(String s){  
  104.         System.out.println(s);  
  105.     }  
  106.   
  107.     public static void main(String[] args){  
  108.         // System.setOut(new PrintStream(new BufferedOutputStream(System.out)));  
  109.         new Main().run();  
  110.     }  
  111. }  

■結果

ooooo----- 500pts. 17th
まぁまぁの成績.