Facebook Hacker Cup Round.1
結果
ooo 887th
Round.1は通過、次はむり。
この形式のコンテストは(GCJとか)
MLEとTLEをあんまり気にしなくていいのが楽である。
Checkpoint
カタラン数(http://ja.wikipedia.org/wiki/%E3%82%AB%E3%82%BF%E3%83%A9%E3%83%B3%E6%95%B0)のような問題。
格子上を(0,0)から(a,b)を通って(x,y)に至るような最短経路の総数がSになるような(a,b),(x,y)のうち、その経路長の最小値を求める。
(0,0)から(a,b)までの最短経路の総数は(a+b)C(a)で求まる。S<=10^7なのでnCr<=10^7となるものを全て列挙し、ある値k=nCrとなる最小のnをkごとに覚えておき、あとは1からsqrt(S)まで回して最小値を出せる。
#include <iostream> #include <algorithm> #include <string> #include <cstring> #include <cstdio> #include <cmath> #define ll long long #define INF 10000000000 using namespace std; ll least_sum[10000001]; ll fact(ll arg){ ll ret = 1; for(ll i=1;i<=arg;i++){ ret *= i; } return ret; } ll c(ll x, ll y){ ll tmp = x; ll ret = 1; for(ll i=0;i<y;i++){ ret *= tmp; tmp--; } return ret / fact(y); } int main(){ ll tmp; for(ll i=0;i<10000001;i++) least_sum[i] = INF; least_sum[1] = 1; for(ll i=1;i<10000001;i++){ for(ll j=1;j<=i/2;j++){ tmp = c(i,j); if(tmp > 10000000) break; least_sum[tmp] = min(least_sum[tmp], i); } } int case_num; int s; cin >> case_num; for(int x=1;x<=case_num;x++){ cin >> s; ll ret = INF; for(int i=1;i<=sqrt(s);i++){ if(s%i == 0){ ret = min(ret, least_sum[i]+least_sum[s/i]); } } printf("Case #%d: %lld \n", x, ret); } }
Recover the sequence
ソート済みの列からログに従ってmerge_sortの逆をしてやると
どう入れ替えたかの数列ができるのでmapに入れてやれば元の数列が出てくる。
若干配列がもったいない
#include <iostream> #include <algorithm> #include <string> #include <cstring> #include <cmath> #include <cstdio> #include <map> #define MP make_pair using namespace std; string str; int t; int n; int array[10001]; int working[10001]; void merge(pair<int,int> a1, pair<int,int> a2){ //copy array for(int i=0;i<n;i++){ working[i] = array[i]; } int lim1 = a1.second - a1.first + 1; int lim2 = a2.second - a2.first + 1; int cnt1 = 0, cnt2 = 0; int tmp; int pos = a1.first; while(lim1 > cnt1 && lim2 > cnt2){ tmp = str[0] - '0'; str.erase(0,1); if(tmp == 1){ working[pos] = array[a1.first + cnt1]; cnt1++; }else{ working[pos] = array[a2.first + cnt2]; cnt2++; } pos++; } while(lim1 > cnt1){ working[pos] = array[a1.first + cnt1]; cnt1++; pos++; } while(lim2 > cnt2){ working[pos] = array[a2.first + cnt2]; cnt2++; pos++; } //write back for(int i=0;i<n;i++){ array[i] = working[i]; } return; } pair<int,int> sep(int begin, int end){ if(begin == end) return MP(begin,end); int mid = floor((double)(end-begin+1)/2); pair<int,int> m_b, m_e; m_b = sep(begin,begin+mid-1); m_e = sep(begin+mid,end); merge(m_b, m_e); return MP(m_b.first, m_e.second); } int main(){ cin >> t; for(int x=1;x<=t;x++){ cin >> n; cin >> str; for(int i=0;i<n;i++){ array[i] = i; } sep(0,n-1); map<int,int> m; for(int i=0;i<n;i++){ m[array[i]] = i+1; } int ret = 1; for(int i=0;i<n;i++){ ret = (31 * ret + m[i]) % 1000003; } printf("Case #%d: %d\n",x, ret); str = ""; } }
Squished Status
DP。
dp[位置][これまでのMAX][右端]
としたけどMAX項はいらなかった。
#include <iostream> #include <algorithm> #include <cstring> #include <string> #include <cstdio> #define ll long long using namespace std; ll dp[1024][256][256]; ll mod = 0xfaceb00c; int main(){ int case_num; int m; string str; int tmp; int len; cin >> case_num; for(int x=1;x<=case_num;x++){ memset(dp, 0, sizeof(dp)); cin >> m; cin >> str; tmp = str[0] - '0'; len = str.size(); //if invalid input if(tmp == 0){ printf("Case #%d: 0\n", x); continue; } dp[0][tmp][tmp] = 1; for(int i=1;i<len;i++){ tmp = str[i] - '0'; for(int j=1;j<=m;j++){ for(int k=1;k<=j;k++){ if(tmp == 0){ if(k*10 <= m){ if(k*10 > j){ dp[i][k*10][k*10] += dp[i-1][j][k] % mod; dp[i][k*10][k*10] %= mod; }else{ dp[i][j][k*10] += dp[i-1][j][k] % mod; dp[i][j][k*10] %= mod; } } }else{ if(k*10 + tmp <= m){ //join right most integer if(k*10 + tmp > j){ dp[i][k*10+tmp][k*10+tmp] += dp[i-1][j][k] % mod; dp[i][k*10+tmp][k*10+tmp] %= mod; }else{ dp[i][j][k*10+tmp] += dp[i-1][j][k] % mod; dp[i][j][k*10+tmp] %= mod; } } if(tmp <= m){ //generate a new integer if(tmp > j){ dp[i][tmp][tmp] += dp[i-1][j][k] % mod; dp[i][tmp][tmp] %= mod; }else{ dp[i][j][tmp] += dp[i-1][j][k] % mod; dp[i][j][tmp] %= mod; } } } } } } ll ret=0; for(int i=1;i<=m;i++){ for(int j=1;j<=m;j++){ ret += dp[len-1][i][j] % mod; ret %= mod; } } printf("Case #%d: %lld\n", x, ret); } }