ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

3092最小公倍数-完全背包问题

2020-12-18 23:33:43  阅读:188  来源: 互联网

标签:背包 prim 公倍数 3092 int maxsize ans include dp


题目描述:
Least common multiple
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1869 Accepted Submission(s): 705

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.

思路:由于拆分的数最终求最小公倍数,由最小公倍数特性,首先考虑只取0-s内的质数,用01背包求解,但是不得行。。。看了别人题解才知道,可能取到质数的次方,比如7,不应该是25而应该是34,因为四是二的次方,而二与三互质,所以三与四是互质的,所以四也应该放进物品里面去,由此转换为完全背包。
还需要考虑的是如果直接用整数的dp取乘积最大值会越界,要把乘积最大改为log求和最大,然后单独取一个ans数组保存最终解,每次修改dp数组时修改ans数组。
01背包错误代码:

#include<iostream>
#include<stdio.h>
#include<vector>
#include<string.h>
#include<string>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<cmath>
#include<unordered_map>
#include<unordered_set>
using namespace std;
const int maxsize = 1e5 + 100;
double dp[maxsize];
int prim[maxsize];
int ans[maxsize];
int n = 0;
bool vis[maxsize] = { 0 };
int s, m;
void get() {
	for (int i = 2; i <= 3000; i++)
	{
		if (!vis[i])prim[n++] = i;
		else continue;
		for (int j = i; j <= 3000; j+=i) {
			vis[j] = 1;
		}
	}
}
int getres() {
    for (int i = 0; i <= s; i++){dp[i] = 0;ans[i]=1;}
    for (int i = 0; prim[i] <= s&&i<n; i++) {
        for (int j = s; j >= prim[i]; j--) {
            double t=log(prim[i]);
            if(dp[j - prim[i]]+t>dp[j]){
            dp[j]=dp[j-prim[i]]+t;
            ans[j]=ans[j-prim[i]]*prim[i]%m;
            }
        }
    }
    return ans[s];
}
int main() {
    get();
    while (cin >> s >> m) {
        cout << getres()<< endl;
    }
    return 0;
}

AC代码:

#include<iostream>
#include<stdio.h>
#include<vector>
#include<string.h>
#include<string>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<cmath>
#include<unordered_map>
#include<unordered_set>
using namespace std;
const int maxsize = 1e5 + 100;
double dp[maxsize];
int prim[maxsize];
int ans[maxsize];
int n = 0;
bool vis[maxsize] = { 0 };
int s, m;
void get() {
	for (int i = 2; i <= 3000; i++)
	{
		if (!vis[i])prim[n++] = i;
		else continue;
		for (int j = i; j <= 3000; j+=i) {
			vis[j] = 1;
		}
	}
}//先求出3000内的质数,然后用完全背包求解。
int getres() {
	for (int i = 0; i <= s; i++) { ans[i] = 1; dp[i] = 0; }
	for (int i = 0; prim[i] <= s&&i<n; i++) {
		for (int j = s; j >= prim[i]; j--) {
			double t = log(double(prim[i]));
			for (int k = 1, p = prim[i];p <= j; p*=prim[i],k++) {
				if (dp[j] < dp[j - p] + k * t) {
					dp[j] = dp[j - p] + k * t;
					ans[j] = ans[j - p] * p % m;
				}
			}
		}
	}
	return ans[s]%m;
}
int main() {
	get();
	while (cin >> s >> m) {
		cout << getres()<< endl;
	}
	return 0;
}

标签:背包,prim,公倍数,3092,int,maxsize,ans,include,dp
来源: https://blog.csdn.net/coodexman/article/details/111397995

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有