2020 CCPC (威海) - L Clock Master(分组背包)

链接: L Clock Master

题意:
题目说了一大堆 , 其实简化一下就是 给你一个 n ,把 n 分解成几个数相加 ,使这几个数的 lcm 最大。
思路:
要使 lcm 最大 ,选的几个数肯定是互质的 ,不然就会产生无用的贡献,所以把每个质数和它的幂次分成一组(每组选一个),然后跑分组背包,求最大贡献就好了。质数 加上它的幂次好像就 3000 来个,最后差不多 1e7 , 一开始 T 了,然后把 log 预处理一下就过了。

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef long long ll;
const int maxn = 3e4 + 7;
int isp[maxn] , pri[maxn];
int k;
double dp[maxn],lg[maxn];
vector< int > vec[maxn];
void sieve(){
    
    
    for(int i = 2; i <= 3e4; i ++){
    
    
        if(isp[i] == 0){
    
    
            pri[k++] = i;
            for(int j = i; j <= 3e4; j += i){
    
    
                isp[j] = 1;
            }
        }
    }
}
int main (){
    
    
    sieve();
    for(int i = 1; i <= 3e4; i ++) lg[i] = log(i);
    for(int i = 0; i < k; i ++){
    
    
        int temp = pri[i];
        while(temp <= 3e4){
    
    
            vec[i].push_back(temp);
            temp *= pri[i];
        }
    }
    for(int i = 0; i < k; i ++){
    
    
        for(int j = 3e4; j >= 0; j --){
    
    
            for(auto  k: vec[i]){
    
    
                if(j >= k)
                dp[j] = max(dp[j] , dp[j - k] + lg[k]);
            }
        }
    }
    int T , n;
    scanf("%d",&T);
    while(T--){
    
    
        scanf("%d",&n);
        printf ("%.9f\n",dp[n]);
    }
}

猜你喜欢

转载自blog.csdn.net/hddddh/article/details/109355524
今日推荐