zoukankan      html  css  js  c++  java
  • 数论 + 完全背包

    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.

    InputThere are many groups of test case.On each test case only two integers S( 0 < S <= 3000) and M( 2<=M<=10000) as mentioned above.OutputOutput the largest LCM modulo M of given S.Sample Input
    6 23
    Sample Output
    6
    
    
    Hint: you can divied 6 as 1+2+3 and the LCM(1,2,3)=6 is the largest so we output 6%23=6.

    题意:将一个数 n 分解成任意个数,这些数的和等于 n ,要求分解出来的这些数的 lcm 最大。
    思路分析:首先被分解出来的数一定两两之间是互质的,因为如果存在一个数与其他的数不互质,那么这个数一定还可以再分成小一点的,确保其与其他的数均互质,同时也会增大lcm。
      这时只要找到小于 n 的所有质数,任意两个质数的 k 次幂均是互质的。这时就可以准变成为一个 完全背包,但是因为答案要对 mod 取余,而dp在转移的过程中又不能去取余,否则会出现错误,这时候可以采用对数,同时在新增一个辅助数组去取余即可。
    代码示例:
    ll n, m;
    vector<ll>ve;
    ll pt[3005];
    
    void init(){
        for(ll i = 2; i <= 3000; i++){
            if (!pt[i]){
                ve.push_back(i);
                for(ll j = i+i; j <= 3000; j += i){
                    pt[j] = 1;
                }
            }
        }  
    }
    double dp[3005];
    ll ans[3005];
    
    int main() {
        //freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
        
        init();
        while(~scanf("%lld%lld", &n, &m)){    
            memset(dp, 0, sizeof(dp));
            for(ll i = 0; i <= n; i++) ans[i] = 1;
            
            for(ll i = 0; i < ve.size(); i++){
                for(ll j = n; j >= ve[i]; j--){
                    ll num = 1;
                    for(ll k = 1; k <= j/ve[i]; k++){
                        num *= ve[i];
                        if (j-num < 0) break;
                        //printf("***** %lf
    ", log10(1.0*k*ve[i]));
                        if (dp[j] < dp[j-num]+log10(1.0*num)){
                            dp[j] = dp[j-num]+log10(1.0*num);
                            ans[j] = ans[j-num]*num%m;
                        }
                        //printf("+++ %lld %lld %lf 
    ", i, j, dp[j]);
                    }         
                }
            }
            printf("%lld
    ", ans[n]);
        }
        return 0;
    }
    
    东北日出西边雨 道是无情却有情
  • 相关阅读:
    php+GTK2 学习第二篇
    PHPMailer + qq邮箱 实现邮件发送
    HTTP状态码200、301、403、404、500等(转)
    LNMP环境搭建(转载)
    PHP+GTK2 初体验,简单计算器客户端
    mysql 用户权限管理(转)
    提高php执行效率的10条编程习惯(转)
    添加php拓展(以phppcntl及phpredis及phppcntl为例)
    centos7 &后台运行 受终端关闭影响问题
    sklearn学习笔记之简单线性回归
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/9147217.html
Copyright © 2011-2022 走看看