洛谷 P4963 美樱的颜料【容斥】【思维】

本文深入探讨了一道关于最大快乐值的算法问题,通过将问题转换为树形结构,利用深度优先搜索策略寻找最优解。文章详细解释了如何通过递归调用实现问题的分解与求解,最终找到以每个叶节点开始的最大快乐值。

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


题目:

传送门


题意:

美樱可以任意选择一种颜料使用,之后,美樱每次都会选择一种颜料 i i i使用,满足使用颜料 i i i后已经使用了的颜料的编号的 g c d gcd gcd尽量大,问美樱可以获得的最大快乐值是多少


分析:

我们来转化下题意,即我们任意选择一种颜料开始,先将其的倍数号数颜料使用,再将其除去本身的最大约数的倍数号数颜料使用 . . . ... ...以此类推
为了方便表示,设 f u f_u fu表示 u u u除去本身的最大约数
在答案计算的过程中, f u f_u fu u u u会重复计算,我们来看个例子:
假如 n f u < m \frac{n}{f_u}<m fun<m,而 n f f u > = m \frac{n}{f_{f_u}}>=m ffun>=m
这时我们的答案表示为: n u ∗ u + ( n f u − n u ) ∗ f u + ( m − n f u ) ∗ f f u \frac{n}{u}*u+(\frac{n}{f_u}-\frac{n}{u})*f_u+(m-\frac{n}{f_u})*f_{f_u} unu+(funun)fu+(mfun)ffu
进一步化简得到: n u ∗ ( u − f u ) + n f u ∗ ( f u − f f u ) + m ∗ f f u \frac{n}{u}*(u-f_u)+\frac{n}{f_u}*(f_u-f_{f_u})+m*f_{f_u} un(ufu)+fun(fuffu)+mffu
这样我们将原序列转化为一棵树,根节点为 1 1 1,每个父节点都是 f u f_u fu,连向子节点 u u u,而边权为 n u ∗ ( u − f u ) \frac{n}{u}*(u-f_u) un(ufu)
于是我们从根节点出发,到每个叶节点的累计答案就是我们以这个叶节点开始的最大快乐值
对上面这个快乐值求最大值即是最终的答案


代码:

// luogu-judger-enable-o2
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#define LL long long 
#define LZX IMU
using namespace std;
inline LL read() {
    LL d=0,f=1;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
    return d*f;
}     
int p[10000005],cnt=0;bool tf[10000005];
int ans=0;
int n=read(),m=read();
void dfs(int u,int fa,int sum)
{
    sum+=min(m,n/u)*(u-fa);
    ans=max(ans,sum);
    for(int i=1;i<=cnt&&u*p[i]<=n;i++)
    {
        int v=u*p[i];
        if(n/v>=m) dfs(v,0,0);
        else dfs(v,u,sum);
        if(!(u%p[i])) break;
    }
    return;
}
int main()
{
    for(int i=2;i<=n;i++)
    {
        if(tf[i]) continue;
        p[++cnt]=i;
        for(int j=1;j<=cnt&&p[j]*i<=n;j++)
        {
            tf[p[j]*i]=1;
            if(!(i%p[j])) break;
        }
    }
    dfs(1,0,0);
    cout<<ans;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值