Skip to content

Instantly share code, notes, and snippets.

@amoshyc
Last active October 4, 2015 02:08
Show Gist options
  • Select an option

  • Save amoshyc/9b46373dfaeb9904ab65 to your computer and use it in GitHub Desktop.

Select an option

Save amoshyc/9b46373dfaeb9904ab65 to your computer and use it in GitHub Desktop.
Poj 2229: Sumsets

Poj 2229: Sumsets

分析

完全沒想到啊…

觀察幾個例子:

2 = 1 + 1
  = 2
3 = 1 + 1 + 1
  = 1 + 2
4 = 1 + 1 + 1 + 1
  = 1 + 1 + 2
  = 2 + 2
  = 4
5 = 1 + 1 + 1 + 1 + 1
  = 1 + 1 + 1 + 2
  = 1 + 2 + 2
  = 1 + 4

藉由 奇數偶數 分開處理,可得到下面想法

Let dp[i] = the number of ways to represent N

奇數就是前一個偶數,每種方法都加上一個 1,所以

dp[i] = dp[i-1]

偶數的話分兩個部分:那些 含有 1 的表示法其它沒有的,例如 4 就是

4 = 1 + 1 + 1 + 1
  = 1 + 1 + 2

4 = 2 + 2
  = 4

前一個部分就是 3 的每種方法再加 1;後一個部分是 2 的每種方法都乘 2,所以式子寫成:

dp[i] = dp[i-1] + dp[i/2]

AC Code

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int N;
long long dp[1000000 + 1];

int solve() {
    dp[1] = 1;
    for (int i = 2; i <= N; i++) {
        if (i & 1)
            dp[i] = dp[i-1];
        else
            dp[i] = dp[i-1] + dp[i / 2];
        dp[i] = dp[i] % 1000000000;
    }

    return dp[N];
}

int main() {
    scanf("%d", &N);
    printf("%d\n", solve());
    return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment