zoukankan      html  css  js  c++  java
  • [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
    ", dp[s]);
    82     }
    83     return 0;
    84 }
    View Code
     
  • 相关阅读:
    (转载)什么时候需要用到try-catch
    直接打印Java的对象时输出的到底是什么
    关于图像语义分割的总结和感悟(转载)
    面经
    石家庄停车位在线预约平台16
    石家庄停车位在线预约平台15
    石家庄停车位在线预约平台14
    石家庄停车位在线预约平台13
    石家庄停车位在线预约平台12
    石家庄停车位在线预约平台11
  • 原文地址:https://www.cnblogs.com/zyxStar/p/4604984.html
Copyright © 2011-2022 走看看