1. 程式人生 > >P2563 [AHOI2001]質數和分解

P2563 [AHOI2001]質數和分解

等於 AD 得到 描述 orange mil DG ems strong

題目描述

任何大於 1 的自然數 n 都可以寫成若幹個大於等於 2 且小於等於 n 的質數之和表達式(包括只有一個數構成的和表達式的情況),並且可能有不止一種質數和的形式。例如,9 的質數和表達式就有四種本質不同的形式:

9 = 2 + 5 + 2 = 2 + 3 + 2 + 2 = 3 + 3 + 3 = 2 + 7 。

這裏所謂兩個本質相同的表達式是指可以通過交換其中一個表達式中參加和運算的各個數的位置而直接得到另一個表達式。

試編程求解自然數 n 可以寫成多少種本質不同的質數和表達式。

輸入輸出格式

輸入格式:

文件中的每一行存放一個自然數 n(2 < n < 200) 。

輸出格式:

依次輸出每一個自然數 n 的本質不同的質數和表達式的數目。

輸入輸出樣例

輸入樣例#1:
2
200
輸出樣例#1:
1
9845164

Solution:

  AH省選的一道水題。

  先篩出$200$以內的素數,然後對於每次詢問$n$,等價於求不超過$n$的素數中選一些加起來等於$n$的方案數,直接跑一遍完全背包,改成計數就好了,狀態$f[i]$表示$i$用素數組成的方案數,初始$f[0]=1$,那麽狀態轉移方程就顯而易見:$f[j]=f[j-prime[i]]+f[j]$。

  

代碼:

 1 #include<bits/stdc++.h>
 2 #define il inline
 3 #define ll long long
 4 #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
 5 #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--)
 6 using namespace std;
 7 int n,f[202],prime[202],cnt;
 8 bool isprime[202];
 9 
10 int main(){
11 ios::sync_with_stdio(0); 12 For(i,2,200){ 13 if(!isprime[i]) prime[++cnt]=i; 14 for(int j=1;j<=cnt&&prime[j]*i<=200;j++){ 15 isprime[prime[j]*i]=1; 16 if(i%prime[j]==0)break; 17 } 18 } 19 while(cin>>n){ 20 memset(f,0,sizeof(f));f[0]=1; 21 For(i,1,cnt) For(j,prime[i],n) f[j]+=f[j-prime[i]]; 22 cout<<f[n]<<endl; 23 } 24 return 0; 25 }

P2563 [AHOI2001]質數和分解