zoukankan      html  css  js  c++  java
  • HDU-3092 Least common multiple---数论+分组背包

    题目链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=3092

    题目大意:

    有一个数字n,现在要把它分解成几个数字相加!然后这几个数字有最小公倍数,题目目的是求出最大的最小公倍数。我们知道所有的素数或者其指数方相加可以表示其它的数字,而把n分解之后求其公倍数自然是互质的数字直接相乘最大,所以目的就变成了求n能分解之后由素数或者其指数数,只要他们之间相互互质就行。

    解题思路:

    将n分解成不同素数之和,这样就是两两互质,求出的lcm是最大的,而且不只是素数之和,可以分解成素数的k次方,这样不同的素数的k次方之间仍然是互质的。

    这样变成了分组背包,每一个素数就是一组,这一组中只能选一个,而背包容量为S。求出最大的价值即可。

    还有一个问题,由于价值过大,需要取模,但是随便取模的话就不好判断大小,所以采用取对数的方法,一个数组记录取对数的值,一个数据记录答案,每次按照取对数的数组的大小判断是否需要更新,需要更新的话直接更新该数组和答案数组。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 ll n, m;
     5 const int maxn = 3000 + 10;
     6 bool is_prime[maxn];
     7 ll prime[maxn], tot, ans[maxn];
     8 double dp[maxn];
     9 void init(int n)
    10 {
    11     for(int i = 2; i <= n; i++)is_prime[i] = 1;
    12     for(int i = 2; i <= n; i++)
    13         if(is_prime[i])
    14         {
    15             prime[tot++] = i;
    16             for(int j = i * 2; j <= n; j += i)is_prime[j] = 0;
    17         }
    18     //for(int i = 0; i < tot; i++)cout<<prime[i]<<endl;
    19 }
    20 int main()
    21 {
    22     init(3000);
    23     while(cin >> n >> m)
    24     {
    25         for(int i = 0; i <= n; i++)dp[i] = 0, ans[i] = 1;
    26         for(int i = 0; i < tot && prime[i] <= n; i++)
    27         {
    28             double tmp = log(prime[i]);
    29             for(int j = n; j >= 1; j--)
    30             {
    31                 ll k = prime[i], cnt = 1;
    32                 while(k <= j)
    33                 {
    34                     if(dp[j] < dp[j - k] + tmp * cnt)
    35                     {
    36                         dp[j] = dp[j - k] + tmp * cnt;
    37                         ans[j] = ans[j - k] * k % m;
    38                     }
    39                     cnt++;
    40                     k *= prime[i];
    41                 }
    42             }
    43         //for(int i = 1; i <= n; i++)cout<<dp[i]<<endl;
    44         }
    45         cout<<ans[n]<<endl;
    46     }
    47     return 0;
    48 }
  • 相关阅读:
    GZIPInputStream 流未关闭引起的内存泄漏问题
    Java ExcutorService优雅关闭方式
    redis pipline
    LeetCode 30与所有单词相关联的字串
    Scala不使用null 而使用Option,None,Some的好处
    记录: 一次解决整型溢出攻击(使用scala,隐式转换)
    Scala 封装可break和continue的foreach循环
    记录: 百度webuploader 分片文件上传java服务器端(spring mvc)示例的优化
    HBase shell 中的十六进制数值表示
    关于getSystemResource, getResource 的总结
  • 原文地址:https://www.cnblogs.com/fzl194/p/9033277.html
Copyright © 2011-2022 走看看