您的位置:首页 > 其它

HDU3692--least common multiple(数论优化+分组背包);DP--数论

2017-08-11 19:06 357 查看
CCPC网络赛开始报名了~ 
欢迎参加——阿里云“智慧航空AI大赛”(报名中...) 

Least common multiple

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 825    Accepted Submission(s): 352


Problem Description

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.

 

Source

2009 Multi-University Training Contest 18 - Host by ECNU
 

Recommend

lcy   |   We have carefully selected several similar problems for you:  3089 3090 3095 3094 3093 

题意:给一个数S,并把S分割成若干个数的和的形式,求这若干个数的最小公倍数的最大值对M取余。

思路:当一个数被分割成未知项,我们需要如何考虑,才能使它的最小公倍数尽可能的大呢?如果里面第i项是第j项的约数,那么他们的最小公倍数就会至少减小他们乘积的2倍,这样求出的解一定不是最优解,所以我们需要把S分割成若干个互质的数,S范围是0到3000,我们可以先对3000以内的素数先打表,那么对于每个小于等于S的每个素数最素数的问题已经显而易见了。我们知道不同素数两两互质,不同素数的次方也互质,但是素数与它本身的次方却不互质,相当于给一个容量为S的背包,有小于等于S的范围内有若干个互质的数,这些互质的数被分为K组(每一组第i个元素是这个素数的i次方),每组最多取一个(如果取两个以上就会产生约数),求把这个背包装满的元素的最大的最小公倍数,这不就是分组背包吗?

        还没完,题目要求对M取模,原因就是,我们求最小公倍数时,DP数组中的元素值有可能超long long,我们一般采取随时取模,当这道题是行不通的,如果随时取模可能影响dp[j]=max(dp[j],dp[  j-k*prime[i]  ]*k*prime[i])的结果,所以我们利用log函数单调递增的特性,对这个状态转移方程取log,然后再用不参与状态转移的另一个数组记录没有取log的结果,就可以啦。

 注意:dp数组声明为double类型。





#include<bits/stdc++.h>
#define inf -0x3f3f3f3f
#define maxn 3005
typedef long long ll;
bool visit[maxn];
int prime[maxn];
double dp[maxn];
ll ans[maxn];
using namespace std;
int num;
void getprime()
{
num=0;
memset(visit,false,sizeof(visit));
prime[0]=1;
for(int i=2;i<=maxn;i++){
if(!visit[i]) prime[++num]=i;
for(int j=1;j<=num&&i*prime[j]<maxn;j++){
visit[i*prime[j]]=true;
if(i%prime[j]==0)
break;
}
}
}
int main()
{
int s,m;
getprime();
while(~scanf("%d%d",&s,&m)){
for(int i=0;i<=s;i++){
ans[i]=1;
dp[i]=0;
}
for(ll i=1;i<num&&prime[i]<=s;i++){
for(ll j=s;j>=prime[i];j--){
for(ll k=prime[i];k<=j;k*=prime[i]){
if(dp[j-k]+log(k*1.0)>dp[j]){
dp[j]=dp[j-k]+log(k*1.0);
ans[j]=ans[j-k]*k%m;
}
}
}
}
cout<<ans[s]<<endl;
}
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp