JMK no matter what

SRM 454

실로 오랜만의 SRM. 첫 자바 매치!!! 두둥!!!

코드를 좀 깔끔하게 짜려는 노력을 하게 되다 보니 (그리고 아직 문법이 100% 익숙하지 않아서 IntelliJ 에 의존해야 하다 보니) 코딩이 많이 느리다. 반복된 연습이 역시 대안이지 싶은데 귀찮아서.. 그래도 둘다 패스했으니 별 불만은 없다. 이지+미디엄에서 시간이 너무 오래 걸려서 하드를 짤 시간이 없어서 결국 포기하고 챌페이즈 진입. 하지만 결국 챌린지 못하고 5x 등. 레이팅은 -7. :-(

그래도 패스패스에 의미를 둬야겠다. 아 그리고 하드도 나중에 결국 풀음.

250 DoubleXor

그냥 구현하면 되는 문제. 실제로는 이 operator 가 commutative 하지 않다는걸 생각 안하고 연산 순서 바꾼 사람들이 있어서 좀 챌린지 꺼리가 있었다고 한다.

lang:java
public class DoubleXor {    
    private int dxor(int a, int b) {
        int mult = 1, ret = 0;
        while(a > 0 || b > 0) {
            int ad = a % 10, bd = b % 10;
            ret += mult * ( (ad ^ bd) % 10 );
            mult *= 10;
            a /= 10;
            b /= 10;
        }
        return ret;
    }
    public int calculate(int N) {
        if(N == 1) return N;
        int ret = dxor(N, N-1);
        for(int i = N-2; i >= 1; --i)
            ret = dxor(ret, i);
        return ret;
    }
}

500 NumbersAndMatches

Standard DP. 숫자 스트링으로 변환하는 법도 구글해서 찾아봐야 하는 이 상황 -_-

lang:java
public class NumbersAndMatches {
    private final int required[] = { 6, 3, 5, 5, 4, 5, 6, 3, 7, 6 };
    private final String maskRep[] = { "1110111", "0010011", "1011101", "1011011", "0111010", "1101011", "1101111", "1010010", "1111111", "1111011"};
    private int[] mask, given;
    private String rep;
    private long[][][] cache;
    private long go(int here, int excess, int allowed) {
        if(here == given.length) {
            if(excess == 0) return 1;
            return 0;
        }
        long ret = cache[here][excess+128][allowed];
        if(ret != -1) return ret;
        ret = 0;
        for(int newDigit = 0; newDigit < 10; ++newDigit) {
            int remove = mask[given[here]] &~ mask[newDigit];
            int add = mask[newDigit] &~ mask[given[here]];
            if(allowed >= Integer.bitCount(remove)) {
                ret += go(here + 1, excess + Integer.bitCount(remove) - Integer.bitCount(add), allowed - Integer.bitCount(remove));
            }
        }
        cache[here][excess+128][allowed] = ret;
        //System.out.println("here = " + here + " excess = " + excess + " allowed = " + allowed + " => " + ret);
        return ret;
    }
    public long differentNumbers(long N, int K) {
        mask = new int[10];        
        for(int i = 0; i < 10; ++i) {
            mask[i] = 0;
            for(int j = 0; j < 7; ++j) {
                mask[i] = mask[i] * 2 + (int)(maskRep[i].charAt(j) - '0');
            }
            if(Integer.bitCount(mask[i]) != required[i] || maskRep[i].length() != 7) {
                System.out.println("Sanity check fail");
            }
        }
        rep = Long.toString(N);
        given = new int[rep.length()];
        for(int i = 0; i < rep.length(); ++i) {
            given[i] = (int)(rep.charAt(i) - '0');
        }
        cache = new long[given.length + 1][256][127];
        for(long[][] row: cache) {
            for(long[] r2: row) {
                fill(r2, -1);
            }
        }
        return go(0, 0, K);
    }
}

1000 MegaSum

원하는 칸의 위치가 (y, x) 라고 하면, 맨 왼쪽 위 칸은 yx 번 더해지고, 그 오른쪽 칸은 y(x-1) 칸 더해지고... 이런 식에서 패턴을 찾아서 O(sqrt(N)) 에 푼다. 실제로는 mul() 에서 a 나 b 가 mod 를 초과할 경우에 ((a % mod) * (b % mod)) % mod 해야 하는데 (a * b) % mod 해서 한번 틀림. :-(

lang:java
public class MegaSum {
    private final long MOD = 1000000007;
    // returns 1+2+3+..+n
    private long sum(long n) {
        return (n*(n+1)) / 2;
    }
    // returns 1^2+2^2+3^2+..+n^2
    private long sumsq(long n) {
        if(n > 100000) {
            System.out.println("oops" + n);
        }
        return (n*(n+1)*(2*n+1)) / 6;
    }
    private long mul(long a, long b) {
        return ((a % MOD) * (b % MOD)) % MOD;
    }
    private long add(long a, long b) { return (a+b+MOD) % MOD; }
    private long increasing(long a, long n, long m, long d) {
        // returns d * (am + (a+1)(m-1) + (a+2)(m-2) + .. + (a+n-1)(m-n+1))
        //       = d * sum(i = 0 to n-1){ (a+i)(m-i) }
        //       = d * sum(i = 0 to n-1){ am - i^2 + mi - ai }
        //       = d * (anm - sum(i){i^2} + (m-a)*sum(i){i} )
        long ret = 0;
        ret = add(ret, mul(mul(a, n), m)); // anm
        ret = add(ret, -sumsq(n-1)); // -sum(i){i^2}
        ret = add(ret, mul(add(m, -a), sum(n-1))); // (m-a)*sum(i){i}
        return mul(ret, d);        
    }
    private long decreasing(long a, long n, long m, long d) {
        // returns d * (am + (a-1)(m-1) + (a-2)(m-2) + .. + (a-n-1)(m-n+1))
        //       = d * sum(i = 0 to n-1){ (a-i)(m-i) }
        //       = d * sum(i = 0 to n-1){ am + i^2 - mi - ai }
        //       = d * (anm + sum(i){i^2} - (m+a)*sum(i){i} )
        long ret = 0;
        ret = add(ret, mul(mul(a, n), m)); // anm
        ret = add(ret, sumsq(n-1)); // sum(i){i^2}
        ret = add(ret, -mul(add(m, a), sum(n-1))); // (m-a)*sum(i){i}
        return mul(ret, d);
    }
    // coords are one-based
    private long solve(long y, long x) {
        long ret = 0;
        long maxring = max(y, x);
        for(long ring = 1; ring <= maxring; ++ring) {
            if(ring % 2 == 0) {
                // vert are increasing
                if(ring <= x) {
                    long firstValue = (ring - 1) * (ring - 1) + 1;
                    long length = min(ring, y);
                    long decrement = x - ring + 1;
                    ret = add(ret, increasing(firstValue, length, y, decrement));
                }
                // horz are decreasing
                if(ring <= y) {
                    long firstValue = ring * ring;
                    long length = min(ring - 1, x);
                    long decrement = y - ring + 1;
                    ret = add(ret, decreasing(firstValue, length, x, decrement));
                }
            }
            else {
                // vert are decreasing
                if(ring <= x) {
                    long firstValue = ring * ring;
                    long length = min(ring, y);
                    long decrement = x - ring + 1;
                    ret = add(ret, decreasing(firstValue, length, y, decrement));
                }
                // horz are increasing
                if(ring <= y) {
                    long firstValue = (ring - 1) * (ring - 1) + 1;
                    long length = min(ring - 1, x);
                    long decrement = y - ring + 1;
                    ret = add(ret, increasing(firstValue, length, x, decrement));
                }
            }
        }
        return ret;
    }
    public int calculate(long N) {
        long ring = 1;
        while(ring * ring < N) {
            ++ring;
        }
        long rem = ring * ring - N;
        long x = min(rem, ring - 1);
        long y = ring - 1 - (rem - x);
        // every coord is 1-based
        ++x; ++y;
        if(ring % 2 == 1) {
            long t = x;
            x = y;
            y = t;
        }
        System.out.println(N + " => (" + y + ", " + x + ")");
        return (int)(solve(y, x) % MOD);
    }
}
2009-12-07 10:14:54 | JM | /logs/topcoder/ | 0 Comments

Leave a comment

春來不似春

About

Eventstream

Pages

Guestbook

Search

Site Admin

Recent Comments