NBUT 1580 調皮的小明 dp類似硬幣分解

NBUT 1580 調皮的小明 dp類似硬幣分解

給定一個數字n(2n200) ,求這個數字可以分解成多少中素數和的形式。
如:9有4中分解方法:9=2+2+2+3,9=2+7,9=2+2+5,9=3+3+3

先將200以內的素數存放在數組primes中,共有cnt個。

dp[i][j]表示將數字i分解成前j個素數和的方法。那麼dp[i][j]=dp[iprimes[k]][k](iprimes[k]andkj) 。注意dp[0][j]全部要初始化成1,因爲本身是素數也算一種。

代碼:

/*************************************************************************
    > File Name: d.cpp
    > Author: gwq
    > Mail: [email protected] 
    > Created Time: 2015年05月01日 星期五 13時07分59秒
 ************************************************************************/

#include <cmath>
#include <ctime>
#include <cctype>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <map>
#include <set>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>

#define INF (INT_MAX / 10)
#define clr(arr, val) memset(arr, val, sizeof(arr))
#define pb push_back
#define sz(a) ((int)(a).size())

using namespace std;
typedef set<int> si;
typedef vector<int> vi;
typedef map<int, int> mii;
typedef long long ll;

const double esp = 1e-5;

int isprime(int n)
{
    if (n <= 1) {
        return 0;
    }
    if (n == 2 || n == 3) {
        return 1;
    }
    for (int i = 2; i * i <= n; ++i) {
        if (n % i == 0) {
            return 0;
        }
    }
    return 1;
}

#define N 210

int dp[N][N], n, primes[N];

int main(int argc, char *argv[])
{
    int cnt = 0;
    for (int i = 2; i <= 200; ++i) {
        if (isprime(i)) {
            primes[cnt++] = i;
        }
    }
    clr(dp, 0);
    for (int i = 0; i < cnt; ++i) {
        dp[0][i] = 1;
    }
    for (int i = 2; i < N; ++i) {
        for (int j = 0; j < cnt; ++j) {
            for (int k = 0; k <= j; ++k) {
                if (i >= primes[k]) {
                    dp[i][j] += dp[i - primes[k]][k];
                }
            }
        }
    }
    while (scanf("%d", &n) != EOF) {
        printf("%d\n", dp[n][cnt - 1]);
    }

    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章