[Swust OJ 838]--最优价值(0-1背包+数学)

题目链接:http://acm.swust.edu.cn/problem/838/

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

Sample Output

3

解题思路:一个有意思的题,考了不少知识点,就相当于给定一个区间的数,找出它们的权值,然后转换为一个0-1背包问题,大致思路如下

     (1)对于a,b,c的值按照给出代码直接模拟求就是了(注意稍稍来点优化,一开始超时了Orz~~~)

     (2)判断一个数是否为素数,打表

     (3)求非素数的价值二分快速幂高精度取模

     (4)求最大总价值0-1背包

代码如下:

 1 //背包,素数表,高精度取模
 2 #include <iostream>
 3 #include <cstring>
 4 #include <cstdio>
 5 #include <algorithm>
 6 #include <cmath>
 7 using namespace std;
 8
 9 #define maxn 60005
10 typedef long long LL;
11 LL wi[maxn], vi[maxn], dp[maxn], n, s;
12 LL prime[maxn] = { 1, 1, 0 };
13
14 void Prime(){
15     for (int i = 2; i <= maxn; i++){
16         if (!prime[i]){
17             for (int j = 2; i*j <= maxn; j++)
18                 prime[i*j] = 1;
19         }
20     }
21 }
22
23 LL mulit_mod(LL a, LL b, LL c){
24     LL t = 1;
25     while (b){
26         if (b & 1) t = a*t % c;
27         b >>= 1;
28         a = a*a % c;
29     }
30     return t;
31 }
32
33
34 LL judge(LL x){
35     LL a, b, vi, t = (LL)sqrt((double)x);
36     if (!(x & 1)){
37         a = 2;
38         b = x / 2;
39     }
40     else{
41         for (a = 2; a <= t; a++){
42             if (x%a == 0){
43                 b = x / a;
44                 break;
45             }
46         }
47     }
48     vi = 0;
49     //优化一下,否则超时
50     //for (LL i = 1; i <= x; i++){
51     //  if (!(x%i)) vi++;
52     //}
53     for (LL i = 1; i <= t; i++){
54         if (!(x%i)){
55             LL e = x / i;
56             if (e > i) vi += 2;
57             else if (e == i)
58                 vi += 1;
59         }
60     }
61     return mulit_mod(a, b, vi);
62 }
63
64 void init(){
65     Prime();
66     for (LL i = 2; i < maxn; i++){
67         wi[i] = i;
68         if (prime[i]) vi[i] = judge(i);
69         else vi[i] = i % 10;
70     }
71 }
72
73 int main(){
74     init();
75     while (~scanf("%lld%lld", &n, &s)){
76         memset(dp, 0, sizeof(dp));
77         for (LL i = 2; i <= n; i++){
78             for (LL j = s; j >= wi[i]; j--)
79                 dp[j] = max(dp[j], dp[j - wi[i]] + vi[i]);
80         }
81         printf("%lld\n", dp[s]);
82     }
83     return 0;
84 }

时间: 2024-12-30 02:55:09

[Swust OJ 838]--最优价值(0-1背包+数学)的相关文章

[Swust OJ 404]--最小代价树(动态规划)

题目链接:http://acm.swust.edu.cn/problem/code/745255/ Time limit(ms): 1000 Memory limit(kb): 65535 Description 以下方法称为最小代价的字母树:给定一正整数序列,例如:4,1,2,3,在不改变数的位置的条件下把它们相加,并且用括号来标记每一次加法所得到的和. 例如:((4+1)+ (2+3))=((5)+(5))=10.除去原数不4,1,2,3之外,其余都为中间结果,如5,5,10,将中间结果相加

swust oj 1026--Egg pain&#39;s hzf

题目链接:http://acm.swust.edu.cn/problem/1026/ Time limit(ms): 3000 Memory limit(kb): 65535 hzf is crazy about reading math recently,and he is thinking about a boring problem. Now there are n integers Arranged in a line.For each integer,he wants to know

SWUST OJ Euclid&#39;s Game(0099)

Euclid's Game(0099) Time limit(ms): 1000 Memory limit(kb): 65535 Submission: 1855 Accepted: 589 Description Starts with two unequal positive numbers (M,N and M>N) on the board. Two players move in turn. On each move, a player has to write on the boar

swust oj 649--NBA Finals(dp,后台略(hen)坑)

题目链接:http://acm.swust.edu.cn/problem/649/ Time limit(ms): 1000 Memory limit(kb): 65535 Consider two teams, Lakers and Celtics, playing a series of NBA Finals until one of the teams wins n games. Assume that the probability of Lakers winning a game is

线段树 [SWUST OJ 764] 校门外的树 Plus Plus

校门外的树 Plus Plus(0764) Time limit(ms): 1000 Memory limit(kb): 65535 Submission: 214 Accepted: 15 Description 西南某科技大学的校门外长度为 L 的公路上有一排树,每两棵相邻的树之间的间隔都是 1 米.我们可以把马路看成一个数轴,马路的一端在数轴 1 的位置,另一端在 L 的位置:数轴上的每个整数点,即 1,2,……,L,都种有一棵树. 现在要将这排树的某一段涂成某种颜色,给定 N 组区间[ 

背包 [POJ 2184 SWUST OJ 145] Cow Exhibition

Cow Exhibition Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9479   Accepted: 3653 Description "Fat and docile, big and dumb, they look so stupid, they aren't much  fun..."  - Cows with Guns by Dana Lyons The cows want to prove to

swust oj 简单背包问题(0032) DFS

Description 设有一个背包可以放入的物品重量为S,现有n件物品,重量分别是w1,w2,w3,…wn. 问能否从这n件物品中选择若干件放入背包中,使得放入的重量之和正好为S. 如果有满足条件的选择,则此背包有解,否则此背包问题无解. Input 输入数据有多行,包括放入的物品重量为s,物品的件数n,以及每件物品的重量(输入数据均为正整数) 多组测试数据. Output 对于每个测试实例,若满足条件则输出“YES”,若不满足则输出“NO“ Sample Input 20 5 1 3 5 7

poj1417 带权并查集+0/1背包

题意:有一个岛上住着一些神和魔,并且已知神和魔的数量,现在已知神总是说真话,魔总是说假话,有 n 个询问,问某个神或魔(身份未知),问题是问某个是神还是魔,根据他们的回答,问是否能够确定哪些是神哪些是魔. 对于这些问题,我们只需要发现,如果回答对方是魔,那么即可以判断出这两个不是同一种族,而如果回答对方是神,那么说明这两个是同一种族,那么就可以用带权并查集合并这些神和魔,然后记录两种分别多少个,这样当所有询问都处理完时我们就可以得到一系列的集合,每个集合分别有它的两个种族的人数,但是此时对于每个

NOJ 1860 保研(0/1背包概率dp)

保研 时间限制(普通/Java):1000MS/3000MS         运行内存限制:65536KByte 总提交:171          测试通过:40 题目描述 对于一些名校而言,保研不仅可以由学校推免,也可以由学生自己向希望保研的学校提出申请,这个过程有点类似于外国学生向学校提交简历等待Offer的过程.但是,投递申请需要亲自去相应学校的研招办递交材料,这就需要一些成本(比如路费等),且每个院校都有自己的录取成功率.现在,请在总成本不超过限制的情况下,求出最大的成功率. 输入 输入