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;
}