JMK no matter what

SRM440 연습

250 열어보니 이전에 돌았던 셋 같은 느낌이 강하게 들었지만 그냥 돌았음. binary search 250 과 DP 500, 그리고 DP 1000 으로 구성된 셋. 500 은 느리긴 느렸는데 풀긴 풀었고, 1000 은 한참 헤매다가 설마 이게 될까? 하고 1시간 17분째에 냈다. 결론은 PPP ㅠ 만세

250 IncredibleMachine

lang:cpp
#include<iostream>
#include<cstring>
#include<algorithm>
#include<sstream>
#include<string>
#include<vector>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<fstream>
#include<cassert>
#include<numeric>
#include<set>
#include<map>
#include<queue>
#include<list>
#include<deque>
using namespace std;

#define FOR(i,a,b) for(int i = (a); i < (b); ++i)
#define REP(i,n) FOR(i,0,n)
#define FORE(it,x) for(typeof(x.begin()) it=x.begin();it!=x.end();++it)
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define CLEAR(x,with) memset(x,with,sizeof(x))
#define sz size()
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef long long ll;

const double eps = 1e-8;

struct IncredibleMachine 
{

    vector<double> solve2(double a, double b, double c)
    {
        double d = b*b - 4*a*c;
        if(d < -eps) return vector<double>();
        if(d < eps) return vector<double>(1, -b / (2*a));
        vector<double> ret;
        ret.push_back((-b + sqrt(d)) / (2*a));
        ret.push_back((-b - sqrt(d)) / (2*a));
        return ret;
    }
    double gravitationalAcceleration( vector <int> x, vector <int> y, int T ) 
    {
        double lo = 0, hi = 1e10;
        REP(it,100)
        {
            double mid = (lo + hi) / 2;
            double takes = 0, speed = 0;
            REP(i,x.sz-1)
            {
                double c = hypot(x[i+1] - x[i], y[i+1] - y[i]);
                double dy = y[i] - y[i+1];
                double a = mid * dy / c;
                vector<double> dt = solve2(0.5 * a, speed, -c);
                assert(dt.sz && dt[0] > 0);
                takes += dt[0];
                speed += dt[0] * a;
            }
            if(takes < T)
                hi = mid;
            else
                lo = mid;

        }
        return hi;
    }
};

500 MazeWandering

내가 괜히 어렵게 푼 듯.. ㅠ 사실 그 외에도 Gaussian elimination 으로도 풀리더라.

lang:cpp
#include<iostream>
#include<cstring>
#include<algorithm>
#include<sstream>
#include<string>
#include<vector>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<fstream>
#include<cassert>
#include<numeric>
#include<set>
#include<map>
#include<queue>
#include<list>
#include<deque>
using namespace std;

#define FOR(i,a,b) for(int i = (a); i < (b); ++i)
#define REP(i,n) FOR(i,0,n)
#define FORE(it,x) for(typeof(x.begin()) it=x.begin();it!=x.end();++it)
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define CLEAR(x,with) memset(x,with,sizeof(x))
#define sz size()
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef long long ll;

pair<double,int> cache1[51][51];
double cache2[51][51];
const int dx[4] = { 1, 0, -1, 0 };
const int dy[4] = { 0, 1, 0, -1 };

struct MazeWandering 
{
    vector<string> m;
    int h, w;
    double goUp(int y, int x, int py, int px)
    {
        double& ret = cache2[y][x];
        if(ret >= 0) return ret;
        ret = 0;
        int child = 0;
        REP(k,4)
        {
            int ny = y + dy[k], nx = x + dx[k];
            if(ny == py && nx == px) continue;
            if(ny < 0 || nx < 0 || ny >= h || nx >= w || m[ny][nx] == 'X') continue;
            ++child;
        }
        if(child == 0) return ret = 1; // we can only go up
        REP(k,4)
        {
            int ny = y + dy[k], nx = x + dx[k];
            if(ny == py && nx == px) continue;
            if(ny < 0 || nx < 0 || ny >= h || nx >= w || m[ny][nx] == 'X') continue;
            ret += 1.0 / (child + 1) * (goUp(ny, nx, y, x) + 1.0);
        }
        ret += 1.0 / (child + 1); // go straight up
        ret *= (child + 1);
        return ret;
    }
    pair<double,int> go(int y, int x, int py, int px)
    {
        if(y < 0 || x < 0 || y >= h || x >= w || m[y][x] == 'X') return make_pair(0, 0);
        pair<double,int>& ret = cache1[y][x];
        if(ret.first >= 0) return ret;
        ret.first = goUp(y, x, py, px);
        ret.second = 1;
        REP(k,4) 
        {
            int ny = y + dy[k], nx = x + dx[k];
            if(ny == py && nx == px) continue;
            pair<double,int> exp = go(ny, nx, y, x);
            ret.first += exp.first + exp.second * goUp(y, x, py, px);
            ret.second += exp.second;
        }
        return ret;
    }
    double expectedTime( vector <string> maze ) 
    {
        m = maze;
        h = m.sz; w = m[0].sz;
        REP(i,h) REP(j,w)
        {
            cache1[i][j].first = -1;
            cache2[i][j] = -1;
        }
        REP(i,h) REP(j,w) if(m[i][j] == '*')
        {
            double expSum = 0;
            int children = 0;
            REP(k,4)
            {
                pair<double,int> expected = go(i + dy[k], j + dx[k], i, j);
                expSum += expected.first;
                children += expected.second;
            }
            return expSum / (children+1); 
        }
        return -1; // oops

    }
};

1000 SquareFreeSets

처음에는 sqrt(500) 까지만 서로 곱할 수 있겠지? 후후 하면서 22 밑까지만 다 돌리고 그 후로 DP 하려다 보니 당연 2x3x71 같은건 서로 곱할 수 있다. -_-;; n/primes[i] 이상이 되는 숫자들은 다 버려도 되겠지? 이거 개수만 유지할까 후후 했더니 안되길래 개수도 몇개 안되겠다 닥치고 벡터에 때려넣기 고고?

해서 간신히 맞음

lang:cpp
#include<iostream>
#include<cstring>
#include<algorithm>
#include<sstream>
#include<string>
#include<vector>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<fstream>
#include<cassert>
#include<numeric>
#include<set>
#include<map>
#include<queue>
#include<list>
#include<deque>
using namespace std;

#define FOR(i,a,b) for(int i = (a); i < (b); ++i)
#define REP(i,n) FOR(i,0,n)
#define FORE(it,x) for(typeof(x.begin()) it=x.begin();it!=x.end();++it)
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define CLEAR(x,with) memset(x,with,sizeof(x))
#define sz size()
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef long long ll;

const ll M = 1000000007;

map<VI,ll> cache[501][501];
struct SquareFreeSets 
{
    VI primes;
    int n, k;
    ll go(int here, int numbers, VI subset)
    {
        if(here == primes.sz) return numbers ? 1 : 0;
        while(!subset.empty() && subset.back() > n/primes[here]) subset.pop_back();
        map<VI,ll>::iterator it = cache[here][numbers].find(subset);
        if(it != cache[here][numbers].end()) return it->second;
        ll& ret = cache[here][numbers][subset];
        ret = go(here+1, numbers, subset) % M;
        if(numbers < k)
        {
            VI next = subset;
            next.pb(primes[here]);
            sort(all(next));
            (ret += go(here+1, numbers+1, next)) %= M;
        }
        REP(i,subset.sz)
        {
            VI next = subset;
            next[i] *= primes[here];
            assert(next[i] <= n);        
            sort(all(next));
            (ret += go(here+1, numbers, next)) %= M;
        }

        printf("here %d, numbers %d, subset", here, numbers);
        REP(i,subset.sz) printf(" %d", subset[i]);
        printf(" => %Ld\n", ret);

        return ret;
    }
    int countPerfect( int N, int K ) 
    {
        n = N; k = K;
        primes.clear();
        REP(i,501) REP(j,501) cache[i][j].clear();
        primes.pb(2);
        for(int i = 3; i <= N; i += 2)
        {
            bool ok = true;
            REP(j,primes.sz) if(i % primes[j] == 0) { ok = false; break; }
            if(ok) primes.pb(i);
        }
        VI nums;
        return go(0, 0, nums);
    }
};
2009-11-08 14:15:55 | JM | /logs/topcoder/ | 1 Comments
ltdtl
2009-11-09 16:13:39
형 블로그 엔트리 연습 vs non-연습으로 만드실 생각은 없으신지 ㅎㄷㄷㄷ

Leave a comment