【cqbzoj】:1330 Prime DP(Ahio2001 質數和分解)

問題 L(1330): Prime

時間限制: 1 Sec  內存限制: 64 MB

題目描述

任何大於 1 的自然數 N,都可以寫成若干個大於等於2且小於等於 N 的質數之和表達式(包括只有一個數構成的和表達式的情況),並且可能有不止一種質數和的形式。 例如9 的質數和表達式就有四種本質不同的形式:9 = 2+5+2 = 2+3+2+2 = 3+3+3 = 2+7 。 這裏所謂兩個本質相同的表達式是指可以通過交換其中一個表達式中參加和運算的各個數的位置而直接得到另一個表達式。 試編程求解自然數 N 可以寫成多少種本質不同的質數和表達式。

輸入

第1行:一個自然數 N , 2≤N≤2000。

輸出

第1行:輸出每一個自然數 N 的本質不同的質數和表達式的數目。

樣例輸入

2

樣例輸出

1

提示

【數據規模】
對於40%的數據 N<=200
對於100%的數據 N<=2000




這是一個套完全揹包模板的題。。

先篩出2000內所有素數

作爲元素來塞揹包

看最後有多少塞法

答案會爆unsigned long long

於是使用高精度。


代碼:

#include<cstdio>
#include<cstring>
#define PRIMEL 2200
#define ULL unsigned long long
bool vis[PRIMEL];
int prime[PRIMEL],tot=1;
inline int max(int a,int b){return a>b?a:b;}
void phi(){
    int tmp=(PRIMEL+1)/2;
    for(int i=2;i<=tmp;i++)
        if(!vis[i])for(int j=i+i;j<PRIMEL;j+=i)vis[j]=true;
    for(int i=2;i<PRIMEL;i++)
        if(!vis[i])prime[tot++]=i;
}
 
struct Num{
    char s[100];
    int len;
    Num(){len=0;memset(s,0,sizeof s);}
    Num(const Num&a){
        memcpy(s,a.s,sizeof s);
        len=a.len;
    }
    void print(){
        for(int i=len-1;i>=0;i--)
            putchar(s[i]+'0');
    }
};
Num operator+(Num a,Num b){
    Num ret;
    int len=max(b.len,a.len);
    for(int i=0;i<len;i++){
        ret.s[i]+=a.s[i]+b.s[i];
        ret.s[i+1]=ret.s[i]/10;
        ret.s[i]%=10;
    }
    if(ret.s[len])len++;
    ret.len=len;
    return ret;
}
 
int n;
Num f[2200];
int main(){
    f[0].len=1;
    f[0].s[0]=1;
    phi();
    scanf("%d",&n);
    for(int i=1;i<tot&&prime[i]<=n;i++)
        for(int j=prime[i];j<=n;j++)
            f[j]=f[j-prime[i]]+f[j];
    f[n].print();
}


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