HDU3092-Least common multiple(数据划分+背包)

Partychen like to do mathematical problems. One day, when he was doing on a least common multiple(LCM) problem, he suddenly thought of a very interesting question: if given a number of S, and we divided S into some numbers , then what is the largest LCM of these numbers? partychen thought this problems for a long time but with no result, so he turned to you for help!
Since the answer can very big,you should give the answer modulo M.
Input
There are many groups of test case.On each test case only two integers S( 0 < S <= 3000) and M( 2<=M<=10000) as mentioned above.
Output
Output the largest LCM modulo M of given S.
Sample Input
6 23
Sample Output
6

Hint: you can divied 6 as 1+2+3 and the LCM(1,2,3)=6 is the largest so we output 6%23=6.

分析:

题意:
将一个数n划分为几个数,这几个数的和为n,求这几个数的最小公倍数的最大值(因为n的划分方法不同,他的最小公倍数可能不同)!最后得结果对m取模!

解析:
要求的最小公倍数,那么这几那么我们把这n划分为几个互斥的数,那么此时几个数的乘积便是最小公倍数,在比较所有不同划分方法所得值得大小取最大值即是n得最小公倍数得最大值!

这里我们考虑到几个互斥得数得乘积比较大,所以想到了每次相乘后都对m取模,但是这样会在中间大小比较的时候出错,所以看了大佬们的取对数!
即:
log(ab)=log(a)+log(b);
结果的大小关系没有发生变化,但是数量级却变小很多!

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#define N 3005

using namespace std;

int Prime[N<<2];
bool vist[N];
double dp[N];
int result[N];

int main()
{
	int n,m;
	memset(vist,true,sizeof(vist));
	Prime[0]=0;
	for(int i=2;i<=3000;i++)
	{
		if(vist[i])
		{
			Prime[++Prime[0]]=i;
			for(int j=i;j<=3000;j+=i)
			{
				vist[j]=false;
			}
		}
	}
	while(~scanf("%d%d",&n,&m))
	{
		for(int i=0;i<=n;i++)
		{
			dp[i]=0;
			result[i]=1;
		}
		for(int i=1;i<=Prime[0]&&Prime[i]<=n;i++)
		{
			double logarithm=log(Prime[i]*1.0);
			for(int j=n;j>=Prime[i];j--)
			{
				for(int k=Prime[i],p=1;k<=j;k*=Prime[i],p++)
				{
					if(dp[j]<dp[j-k]+p*logarithm)
					{
						dp[j]=dp[j-k]+p*logarithm;
						result[j]=((result[j-k]%m)*(k%m))%m;
					}
				}
			}
		}
		printf("%d\n",result[n]);
	}
	return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值