2020 ICPC(威海) —L. Clock Master(质数+分组背包)

L. Clock Master

题目大意:

将题目转化一下就是把n拆分为若干个数的和,使得这些数的lcm最大,输出log(lcm)。

思路:

如果分解出的数中两个数成倍数的关系的话,那么其中小的那个数就是没有任何意义的(你细品)。使lcm最大也就是任意两个数之间尽量互素。考虑分组背包,一个素数的不同幂次为一组中的不同物品,问题即转化为了在每组只能选取一个数,求乘积的最大值(不同组中的数是不同素数的幂次,一定互素)
但是如果你直接相乘求lcm的话会爆long long ,那么题目里面要我们求的是log(lcm)。那么我们高中的时候就学过log(a*b) =log a + log b。所以我们先预处理出前3e4的log值,然后把乘法直接转化为加法即可。

AC Code

#include<bits/stdc++.h>
using namespace std;
const int N=3e4+10;
double LOG[N],dp[N];
int primes[N],ans[N];
int cnt=0;
int main()
{
    
    
    int t;
    scanf("%d",&t);
    for(int i=1;i<N;i++) LOG[i]=log(i); 
    for(int i=2;i<N;i++)    //处理出所有的素数
    {
    
    
        if(ans[i]==0) primes[cnt++]=i;
        for(int j=0;j<cnt&&i*primes[j]<N;j++)
        {
    
    
            ans[i*primes[j]]=1;
            if(i%primes[j]==0) break;
        } 
    }
    for(int i=0;i<cnt;i++)
    {
    
    
        for(int j=N-1;j>=primes[i];j--)
        {
    
    
            for(int k=primes[i];k<=j;k*=primes[i])
                dp[j]=max(dp[j],dp[j-k]+LOG[k]);
        }
    }
    while(t--)
    {
    
    
        int b;
        scanf("%d",&b);
        printf("%.9f\n",dp[b]);
    }
    //system("pause");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Stevenwuxu/article/details/113034354
今日推荐