• hdu 3092 简单数论+分组背包dp


    Least common multiple

    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.

    【题意】给你一个数N和结果的mod M。求如何划分N,使得子集和为N的集合的LCM最大。

    从数学上来看,lcm(a, b) = a/gcd(a, b)*b, 只有在gcd(a, b)为1的时候,lcm最大,也就是分割的集合里的每一个数都是互质的。

    每个质数和它的幂次作为分组背包的一组(因为每个数互质的时候,lcm最大);由于dp的时候取模会导致dp结果不正确,而不取模又会导致dp结果过大。由对数的单调性,和对数加法和乘法的性质,dp[i]为i的对数的分割的最大lcm。同时需要另一个数组保留最后结果。

    代码如下:

     1 #include <iostream>
     2 #include <cmath>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <cstdio>
     6 using namespace std;
     7 #define ll long long
     8 
     9 int prime[3100], pri_size = 0;
    10 bool isprime[3100];
    11 void sieve(int num)
    12 {
    13     memset(prime, 0, sizeof(prime));
    14     memset(isprime, true, sizeof(isprime));
    15     isprime[0] = isprime[1] = false;
    16     for(int i = 2; i <= num; i++ ) {
    17         if(isprime[i]) {
    18             prime[pri_size++] = i;
    19            // cout << i << " ";
    20         }
    21         for(int j = 0; i*prime[j] <= num; j++){
    22             isprime[i*prime[j]] = false;
    23             if(i%prime[j] == 0) break;
    24         } 
    25     }
    26    // cout << endl;
    27 }
    28 int main()
    29 {
    30     int n, m;
    31     sieve(3000);
    32     while(cin >> n >> m) {
    33         int ans[3100]; 
    34         double dp[3100];
    35         for(int i = 0; i <= n; i++ ) {dp[i] = 0; ans[i] = 1;}
    36         
    37         for(int i = 0; i < pri_size && prime[i] <= n; i++) {
    38             double log_p = log(prime[i]);
    39             for(int j = n; j >= 1; j--) {
    40                 ll pri = prime[i], cnt = 1;
    41                 while(pri <= j) {
    42                     if(dp[j] < dp[j-pri] + log_p*cnt) {
    43                         dp[j] = dp[j-pri] + log_p * cnt;
    44                         ans[j] = ans[j-pri] * pri % m;
    45                     }
    46                     cnt++;
    47                     pri *= prime[i];
    48                 }
    49             }
    50         }
    51         cout << ans[n] << endl;
    52     }
    53 }
    View Code

  • 相关阅读:
    Solaris 11 system package 安装与更新(如:assembler)
    JS实现页面内跳转
    使用Eclipse进行嵌入式软件开发
    Eclipse下C++标准库报错::mbstate_t has not been declared
    嵌入式ARM开发环境搭建
    CCS内存数据转成图片
    RESET
    Android 圆角研究
    Java 重写必须满足的条件
    android 社会化分享集成
  • 原文地址:https://www.cnblogs.com/ZiningTang/p/10478916.html
Copyright © 2020-2023  润新知