Checkpoint
数学の問題。パスカルの三角形を使って解きました。下のコードでは、len[i]に最短路のパターン数がiになる場合における始点-終点間のマンハッタン距離の最小値を格納しています。len[]が分かれば、答えはlen[j] + len[S/j]の最小値です(jはSの約数)。
- const int MAX = 10000000;
- const int INF = 100000000;
- int comb[2][10000];
- int len[MAX+1];
- void solve() {
- for (int i = 0; i <= MAX; i++)
- len[i] = i;
- memset(comb, 0, sizeof(comb));
- comb[0][0] = 1;
- for (int i = 0; i < 10000; i++) {
- int now = i&1;
- int next = (i+1)&1;
- if (i > 0) {
- for (int j = 0; j <= i; j++) {
- int k = comb[now][j];
- if (k <= MAX)
- len[k] = min(len[k], i);
- }
- }
- memset(comb[next], 0, sizeof(comb[next]));
- for (int j = 0; j <= i; j++) {
- comb[next][j] = min(INF, comb[next][j] + comb[now][j]);
- comb[next][j+1] = min(INF, comb[next][j+1] + comb[now][j]);
- }
- }
- int R, S;
- scanf("%d", &R);
- for (int i = 0; i < R; i++) {
- scanf("%d", &S);
- int ret = INF;
- for (int j = 1; j * j <= S; j++) {
- if (S % j == 0)
- ret = min(ret, len[j] + len[S/j]);
- }
- printf("Case #%d: %d\n", i+1, ret);
- }
- }
Recover the Sequence
実装問題。最初にord[i] = iとした配列を用意。デバッグ情報を元にマージソートを再現します。ソート完了後のord[]を見ることで、iはもともとord[i]番目にあったんだなということが分かります。
- const LL MOD = 1000003;
- vector<int> merge_sort(vector<int> arr) {
- int n = arr.size();
- if (n <= 1)
- return arr;
- int mid = n/2;
- vector<int> arr1(arr.begin(), arr.begin()+mid);
- arr1 = merge_sort(arr1);
- vector<int> arr2(arr.begin()+mid, arr.end());
- arr2 = merge_sort(arr2);
- unsigned int p = 0, q = 0;
- for (;p < arr1.size() && q < arr2.size();) {
- int c = getchar();
- if (c == '1') {
- arr[p+q] = arr1[p];
- ++p;
- }
- else {
- arr[p+q] = arr2[q];
- ++q;
- }
- }
- for (;p < arr1.size(); p++)
- arr[p+q] = arr1[p];
- for (;q < arr2.size(); q++)
- arr[p+q] = arr2[q];
- return arr;
- }
- void solve() {
- int T;
- int N;
- vector<int> ord;
- vector<int> pos;
- cin >> T;
- for (int t = 0; t < T; t++) {
- cin >> N;
- ord.resize(N);
- for (int i = 0; i < N; i++)
- ord[i] = i;
- getchar();
- ord = merge_sort(ord);
- pos.resize(N);
- for (int i = 0; i < N; i++)
- pos[ord[i]] = i+1;
- LL ret = 1;
- for (int i = 0; i < N; i++)
- ret = (31 * ret + pos[i]) % MOD;
- printf("Case #%d: %I64d\n", t+1, ret);
- }
- }
Squished Status
DPの問題。dp[i][j]にcompressed messageのi番目まで見終わったとき最後の文字コードがjとなっているときの場合の数を格納すればOKです。
- const LL MOD = 4207849484LL;
- LL dp[1024][256];
- void solve() {
- int N;
- scanf("%d", &N);
- for (int t = 0; t < N; t++) {
- int M;
- string comp;
- cin >> M >> comp;
- int len = comp.length();
- memset(dp, 0, sizeof(dp));
- dp[0][0] = 1;
- for (int i = 0; i < len; i++) {
- for (int j = 0; j <= M; j++) {
- if (dp[i][j] == 0)
- continue;
- int d = comp[i] - '0';
- int k = 10 * j + d;
- if (0 < k && k <= M)
- dp[i+1][k] = (dp[i+1][k] + dp[i][j]) % MOD;
- if (k != d && 0 < d && d <= M)
- dp[i+1][d] = (dp[i+1][d] + dp[i][j]) % MOD;
- }
- }
- LL ret = 0;
- for (int i = 1; i <= M; i++)
- ret = (ret + dp[len][i]) % MOD;
- printf("Case #%d: %I64d\n", t+1, ret);
- }
- }