UVA - 1213

来源:互联网 发布:天刀天香捏脸数据图 编辑:程序博客网 时间:2024/05/20 20:01

分析:

以d[ i ][ j ] 表示数i分解为j个素数的所有方法; 第一个想到的状态转移方程  d[ i ][ j ]  += d[ i -k ][ j-1 ] (k为比i小的素数),但改状态转移方程并不正确,如d[ 7 ][ 3 ]转移至d[ 5 ] [ 2 ];

5 可分解为 3+2 与刚才的2重复,换句话数d[ i ][ j ] 只依赖  d[ i -k ][ j-1 ] 中由j-1个素数组成并且所有素数都与k不同的那一部分;


这样可以考虑正向枚举所有1120内的素数,那么d[ i ] [ j ] 转移时剪掉当前素数k之后,状态d[ i -k ][ j-1 ]此时肯定只包含由比k小的素数组成的结;


#include <map>#include <vector>#include <cstdio>#include <cmath>#include <cstring>#include <iostream>#include <algorithm>#define INF 10000000using namespace std;typedef long long LL;const int maxn = 1120;vector<int> primes;int vis[maxn+10];void init_primes_table(){memset(vis,0,sizeof(vis));int m=sqrt(maxn+0.5);for(int i=2;i<=m;i++)if(!vis[i])   for(int j=i*i;j<=maxn;j+=i) vis[j]=1;for(int j=2;j<=maxn;j++)if(!vis[j])    primes.push_back(j);}int d[maxn+10][15];int main(){    init_primes_table();    memset(d,0,sizeof(d)); d[0][0]=1;    int lim=primes.size();    for(int i=0;i<lim;i++){        for(int j=14;j>=1;j--){            for(int k=maxn;k>=primes[i];k--){            d[k][j]+=d[k-primes[i]][j-1];            }        }    }    int n,m;    while(scanf("%d %d",&n,&m)==2){            if(!n&&!m) break;       printf("%d\n",d[n][m]);    }    return 0;}



0 0
原创粉丝点击