2020CCPC(威海) - Clock Master(数论+分组背包)

题目大意:给出一个数字 n ,要求分解成:a[ 0 ] + a[ 1 ] + ... +  a[ m ] = n,( m 没有约束 ),使得 lcm( a[ 0 ] , a[ 1 ] , ... a[ m ] ) 最大,输出这个最大值的对数

题目分析:看到 lcm 就可以去思考如何快速求出 n 个数的 lcm,比较简单的一种方法就是将每个数进行质因子分解,对于每个质因子 p 来说,取 n 个数中 p^k[ i ] 的最大值,就是质因子 p 的贡献了,所有质因子的贡献的乘积就是需要求的 lcm

所以这个题目的模型就比较简单了,尝试将 n 分解为 p_{1}^{e1}+p_{2}^{e2}+p_{3}^{e3}+...+p_{k}^{ek}=n 使得 p_{1}^{e1}*p_{2}^{e2}*p_{3}^{e3}*...*p_{k}^{ek} 尽可能大,到此为止,再看一下题面需要求的对数,不难发现对数只是为了保证精度的,因为对数函数是单调递增的,所以套上对数的公式将目标转换为:使得 log(p_{1}^{e1})+log(p_{2}^{e2})+log(p_{3}^{e3})+...+log(p_{k}^{ek}) 尽可能大

换句话说,花费 p^i 的容量可以获得 log(p^i) 的价值,且目标容量为 n,且每个质因子 p 只能选择一种幂次,这就是分组背包的模板题目了,设质数的幂次集合为 P = \left\{ p^i : p \in Prime, i \in Z^+ \right\},那么 |P\cap[1,n]|=O(\frac{n}{log(n)}),可以先预处理一下,时间复杂度为 O( n * n / logn ),然后就可以 O( 1 ) 查询了

代码:
 

//#pragma GCC optimize(2)
//#pragma GCC optimize("Ofast","inline","-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
using namespace std;
     
typedef long long LL;
     
typedef unsigned long long ull;
     
const int inf=0x3f3f3f3f;

const int N=3e4+100;

double ans[N],Log[N];

int cnt,pri[N];

bool vis[N];

double dp[N];

void P()
{
	for(int i=2;i<N;i++)
	{
		if(!vis[i])
			pri[cnt++]=i;
		for(int j=0;j<cnt&&pri[j]*i<N;j++)
		{
			vis[pri[j]*i]=true;
			if(i%pri[j]==0)
				break;
		}
	}
}

void init()
{
	for(int i=1;i<N;i++)
		Log[i]=log(i);
	for(int i=0;i<N;i++)
		dp[i]=0;
	dp[0]=0;
	for(int i=0;i<cnt;i++)//枚举质数 
		for(int j=N-1;j>=pri[i];j--)//容量 
			for(int k=pri[i];k<N;k*=pri[i])//当前的幂次 
				if(j>=k)
					dp[j]=max(dp[j],dp[j-k]+Log[k]);
}

int main()
{
#ifndef ONLINE_JUDGE
//  freopen("data.in.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);
	P();
	init();
	int w;
	cin>>w;
	while(w--)
	{
		int n;
		scanf("%d",&n);
		printf("%.10f\n",dp[n]);
	}














    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/109285171
今日推荐