[luogu4161 SCOI2009]游戏 (DP)

本文深入解析了游戏问题中的一种动态规划算法,通过将问题转化为寻找循环节的最小公倍数,利用质数的最高次幂进行DP求解,强调了方案的灵活性,即使最终结果不等于目标值n也依然可行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[luogu4161 SCOI2009]游戏 (DP)

传送门

Solution

可以发现实际上是把n分为几个循环节,然后找循环节的\(lcm\)是这次的排数
\(lcm\)必然是一些最高次幂的质数的成积,那么就dp求一下所有情况就好了
PS:注意并不是必须要等于n小于n都行,因为可以在后面补1而\(lcm\)不变

Code

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define Re register
#define int long long
#define F(i,a,b) for(Re int i=(a);i<=(b);i++)
#define R(i,a,b) for(Re int i=(b);i>=(a);i--)
using namespace std;

inline int read() {
    int x=0,f=1;char c=getchar();
    while(!isdigit(c)) {if(c=='-')f=-f;c=getchar();}
    while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
    return x*f;
}

const int N=1010;
bool vis[N];
int n,tot,ans;
int pri[N],f[N];

void init() {
    F(i,2,n) {
        if(!vis[i]) pri[++tot]=i;
        for(Re int j=1;j<=tot&&i*pri[j]<=n;j++) {
            vis[i*pri[j]]=1;
            if(i%pri[j]==0) break; 
        }
    }
}

signed main() {
    n=read();
    init();
//  F(i,1,tot) printf("%d ",pri[i]);cout<<endl;
    f[0]=1;
    F(i,1,tot) R(j,0,n) for(Re int k=pri[i];j+k<=n;k*=pri[i]) f[j+k]+=f[j]; 
    F(i,0,n) ans+=f[i];
    printf("%lld",ans);
    return 0;
}
posted @ 2018-10-02 16:38 Menteur_Hxy 阅读( ...) 评论( ...) 编辑 收藏
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值