[Swust OJ 838]--最优价值(0-1背包+数学)
2015-06-28 00:52
302 查看
题目链接:http://acm.swust.edu.cn/problem/838/
Time limit(ms): 1000 Memory limit(kb): 10000
Description
我们定义了这个一个函数:
对于每一个非素数X可以通过Judge函数得到A,B,C三个数。X的价值就定义为V=(A^B)%C
对于素数Y的价值V定义为:V=Y%10
现在给你一个大于1的正整数N,那么你将会有一个区间[2,N],现在你的问题是从中选择若干个互不相同的数,使其和不大于给定的另一个数S。同时使这些互不相等的数的价值总和最大。所以问题就是给定N和S,求出满足上诉条件的最大总价值。
Input
输入两个数N,S.(2<=N<=20000,2<=S<=60000)
Output
输出最大的总价值。
Sample Input
Sample Output
解题思路:一个有意思的题,考了不少知识点,就相当于给定一个区间的数,找出它们的权值,然后转换为一个0-1背包问题,大致思路如下
(1)对于a,b,c的值按照给出代码直接模拟求就是了(注意稍稍来点优化,一开始超时了Orz~~~)
(2)判断一个数是否为素数,打表
(3)求非素数的价值二分快速幂高精度取模
(4)求最大总价值0-1背包
代码如下:
View Code
Time limit(ms): 1000 Memory limit(kb): 10000
Description
我们定义了这个一个函数:
void Judge(int x, int &A, int &B, int &C) { int i; for (A = 2; A<x; A++) if (x%A == 0) { B = x / A; break; } C = 0; for (i = 1; i <= x; i++) if (x%i == 0) C++; }
对于每一个非素数X可以通过Judge函数得到A,B,C三个数。X的价值就定义为V=(A^B)%C
对于素数Y的价值V定义为:V=Y%10
现在给你一个大于1的正整数N,那么你将会有一个区间[2,N],现在你的问题是从中选择若干个互不相同的数,使其和不大于给定的另一个数S。同时使这些互不相等的数的价值总和最大。所以问题就是给定N和S,求出满足上诉条件的最大总价值。
Input
输入两个数N,S.(2<=N<=20000,2<=S<=60000)
Output
输出最大的总价值。
Sample Input
3 3 |
3 |
(1)对于a,b,c的值按照给出代码直接模拟求就是了(注意稍稍来点优化,一开始超时了Orz~~~)
(2)判断一个数是否为素数,打表
(3)求非素数的价值二分快速幂高精度取模
(4)求最大总价值0-1背包
代码如下:
//背包,素数表,高精度取模 #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; #define maxn 60005 typedef long long LL; LL wi[maxn], vi[maxn], dp[maxn], n, s; LL prime[maxn] = { 1, 1, 0 }; void Prime(){ for (int i = 2; i <= maxn; i++){ if (!prime[i]){ for (int j = 2; i*j <= maxn; j++) prime[i*j] = 1; } } } LL mulit_mod(LL a, LL b, LL c){ LL t = 1; while (b){ if (b & 1) t = a*t % c; b >>= 1; a = a*a % c; } return t; } LL judge(LL x){ LL a, b, vi, t = (LL)sqrt((double)x); if (!(x & 1)){ a = 2; b = x / 2; } else{ for (a = 2; a <= t; a++){ if (x%a == 0){ b = x / a; break; } } } vi = 0; //优化一下,否则超时 //for (LL i = 1; i <= x; i++){ // if (!(x%i)) vi++; //} for (LL i = 1; i <= t; i++){ if (!(x%i)){ LL e = x / i; if (e > i) vi += 2; else if (e == i) vi += 1; } } return mulit_mod(a, b, vi); } void init(){ Prime(); for (LL i = 2; i < maxn; i++){ wi[i] = i; if (prime[i]) vi[i] = judge(i); else vi[i] = i % 10; } } int main(){ init(); while (~scanf("%lld%lld", &n, &s)){ memset(dp, 0, sizeof(dp)); for (LL i = 2; i <= n; i++){ for (LL j = s; j >= wi[i]; j--) dp[j] = max(dp[j], dp[j - wi[i]] + vi[i]); } printf("%lld\n", dp[s]); } return 0; }
View Code
相关文章推荐
- 推荐近期15个 Node.js 开发工具
- 告别臃肿~精简安装Visual Studio 2012
- android NDK中sqlite3数据库的使用
- Codeforces Round #310 (Div. 1) A. Case of Matryoshkas 水题
- spring学习笔记(1)——spring介绍
- [Codeforces Round #310 (Div. 2)] #ABC题解
- Codeforces Round #310 (Div. 2)
- 博客订阅Feed地址托管到GAE
- LeetCode——Search for a Range
- DP项目开发随记5-攀爬初步完成
- 有了装逼大全,谁也阻止不了我装逼了
- 定义一个Block
- PHP本地实现虚拟域名访问:Apache虚拟主机配置
- leetcode解题报告228——Summary Ranges
- Zxing在CameraManager.get().closeDriver()报错
- Python 3.5 终于将 Type Hint(类型提示)官方化
- php页面静态化—优化页面响应时间
- Android横向滑动选项卡
- [综] Sparse Representation 稀疏表示
- SDWebImage