1025: [SCOI2009]游戏 线性筛素数+DP

本文介绍了一种解决特定数学问题的方法:将整数N拆分成若干个正整数的组合,使得这些正整数的最小公倍数(LCM)的方案数量。通过线性筛法获取素数,并利用动态规划算法来高效地找出所有可能的组合。

题目即将N进行拆分,求各部分的LCM有几种。
我们考虑对于一个可能的LCM的值,如果这个值可以由不互质的几部分得到,那么它一定可以由互质的几部分得到。
那么就可以先线性筛出素数。然后把每个素数的k(k=1,2,3…)看成物品往背包里装,就成了简单DP啦。

#include<iostream>
#include<cstdio>
#define ll long long 
using namespace std;
int prime[1005];
int n;
ll f[1005][1005],ans;
bool flag[1005];
inline void get_prime()
{
    for (int i=2;i<=n;i++)
    {
        if (!flag[i]) prime[++prime[0]]=i;
        for (int j=1;j<=prime[0]&&i*prime[j]<=n;j++)
        {
            flag[i*prime[j]]=1;
            if (i%prime[j]==0) break;
        }
    }
}
int main()
{
    scanf("%d",&n);
    get_prime();
    f[0][0]=1;
    for (int i=1;i<=prime[0];i++)
    {
        for (int j=0;j<=n;j++) f[i][j]=f[i-1][j];
        for (int j=0;j<=n;j++)
            for (int k=prime[i];k<=j;k*=prime[i])
                f[i][j]+=f[i-1][j-k];
    }
    for (int i=0;i<=n;i++) ans+=f[prime[0]][i];
    cout << ans << endl;
    return 0;
}   
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值