P1734 最大约数和

线性筛+背包

讲道理这道题在线性筛后就让我们想到暴力的做法,毕竟写了\(n \leq 1000\)

其实你要用背包做的。

dp也很显然的,就用一维来表示和不超过\(i\)的最大的所谓约数和。

为什么是所谓的呢?你约数和是包括自己的。所以在这道题中你要自己把数字本身手工去掉。

当然不是叫你在线性筛的时候弄掉,在dp的时候抠掉即可。

线性筛不难的,就那么几种情况,手工推推式子就可以得到了。

讲道理这题还pj-

代码:

#include<cstdio>
#include<algorithm>
const int maxn = 1005, N = maxn - 5;
bool notprime[maxn];
int prime[maxn], tot;
int ysh[maxn], mm[maxn];
int dp[maxn];
int n;
void init()
{
    notprime[1] = true; ysh[1] = 1; mm[1] = 1;
    for(int i = 2; i <= N; i++)
    {
        if(!notprime[i])
        {
            prime[++tot] = i;
            ysh[i] = mm[i] = i + 1;
        }
        for(int j = 1; j <= tot && i * prime[j] <= N; j++)
        {
            notprime[i * prime[j]] = true;
            if(i % prime[j])
            {
                ysh[i * prime[j]] = ysh[i] * ysh[prime[j]];
                mm[i * prime[j]] = prime[j] + 1;
            }
            else
            {
                ysh[i * prime[j]] = ysh[i] / mm[i] * (mm[i] * prime[j] + 1);
                mm[i * prime[j]] = mm[i] * prime[j] + 1;
                break;
            }
        }
    }
}
int main()
{
    init();
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
    {
        dp[i] = ysh[i] - i;
        for(int j = 1; j < i; j++)
        {
            dp[i] = std::max(dp[i], dp[j] + ysh[i - j] - (i - j));
        }
    }
    //for(int i = 1; i <= n; i++) printf("%d ", dp[i]);
    //printf("\n");
    printf("%d\n", dp[n]);
    return 0;
}

转载于:https://www.cnblogs.com/Garen-Wang/p/9892823.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值