読者です 読者をやめる 読者になる 読者になる

Google Code Jam 2010 Qualification Round

参加しました.
先に言い訳をしておくと,酔った頭で寝起きに解いた上に,
久しぶりのプログラミングだったのでぼろぼろでした.


Google Code Jam
Code Jam Statistics (2016)


ちゃんと問題を読まずに10^8だから32bit-intでいけるギリギリなんだなと思ってたら,
思いっきりあふれて答えがマイナスになり,あせって直しましたが一ヶ所直し忘れwrong answerになりました.
というわけで,76点.


とりあえず解答をみやすく整形したものを載せておく.
本番提出したものは,昔作った入出力用のテンプレートを作ったので読みにくいです.
実行時に標準入出力先を指定しなくて済むので楽なだけ.

Snapper Chain

結局はKの2進法表記の下位N bitを左右反転させたものと各snapperのON-OFFが対応します.
なので,K%(1<

import java.util.*;
public class A {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        for(int cases=1;cases<=n;++cases){
            int N = sc.nextInt();
            int K = sc.nextInt();
            System.out.println("Case #"+cases+": "+((K%(1<<N)==(1<<N)-1)?"ON":"OFF"));
        }
    }
}

Fair Warning

a_1

import static java.util.Arrays.*;
import java.util.*;
import java.math.*;
public class B {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        for(int cases=1;cases<=n;++cases){
            int N = sc.nextInt();
            BigInteger[] ts = new BigInteger[N];
            for(int i=0;i<N;++i)ts[i]=sc.nextBigInteger();
            sort(ts);
            BigInteger gcd = ts[1].subtract(ts[0]);
            for(int i=2;i<N;++i)gcd = gcd.gcd(ts[i].subtract(ts[0]));
            BigInteger ans=gcd.subtract(ts[0].mod(gcd)).mod(gcd);
            System.out.println("Case #"+cases+": "+ans);
        }
    }
}

Theme Park

ジェットコースターで100000000000000000ユーロ儲けるかもしれないと皮算用している人のため問題です.
組み合わせがどのグループから乗り始めるかの組み合わせがN通りしかないので,そのうちループします.
ループ部分をまとめて処理すれば終わり.必ずlongで計算すること.

import java.util.*;
public class C {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        for(int cases=1;cases<=n;++cases){
            long R = sc.nextLong();
            long k = sc.nextLong();
            int N = sc.nextInt();
            long[] g = new long[N];
            for(int i=0;i<N;++i)g[i]=sc.nextInt();
            //grouping
            long[] size = new long[N];
            int[] next = new int[N];
            for(int i=0;i<N;++i){
                int j=i;
                while(size[i]+g[j]<=k){
                    size[i]+=g[j];
                    j=(j+1)%N;
                    if(j==i)break;
                }
                next[i]=j;
            }
            //loop detecting
            int cs = 0;
            int initL = 0;
            long initC = 0;
            boolean[] check = new boolean[N];
            while(!check[cs]){
                initL++;
                initC+=size[cs];
                check[cs]=true;
                cs=next[cs];
            }

            int css = cs;
            long sum = 0;
            ArrayList<Long> loop = new ArrayList<Long>();
            while(true){
                sum+=size[css];
                loop.add(size[css]);
                css=next[css];
                if(cs==css)break;
            }
            long ans = 0;
            if(R<=initL){
                int j=0;
                for(int i=0;i<R;++i){
                    ans+=size[j];
                    j=next[j];
                }
            }else{
                ans+=initC;
                ans+=(R-initL)/loop.size()*sum;
                for(int i=0;i<(R-initL)%loop.size();++i)ans+=loop.get(i);
            }
            System.out.println("Case #"+cases+": "+ans);
        }
    }
}

実際はループ検出などしなくても,1億回程度なので15秒ほどで解けるため次のようなプログラムで十分.

import java.util.*;
public class C {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        for(int cases=1;cases<=n;++cases){
            long R = sc.nextLong();
            long k = sc.nextLong();
            int N = sc.nextInt();
            long[] g = new long[N];
            for(int i=0;i<N;++i)g[i]=sc.nextInt();

            long[] size = new long[N];
            int[] next = new int[N];
            for(int i=0;i<N;++i){
                int j=i;
                while(size[i]+g[j]<=k){
                    size[i]+=g[j];
                    j=(j+1)%N;
                    if(j==i)break;
                }
                next[i]=j;
            }
            long ans = 0;
            int j=0;
            for(int i=0;i<R;++i){
                ans+=size[j];
                j=next[j];
            }
            System.out.println("Case #"+cases+": "+ans);
        }                                                                                                                                                         
    }
}