zoukankan      html  css  js  c++  java
  • hdu3092

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3092

    题目描述:将一个数拆分成几个数之和,问这几个数能得到的最大的最小公倍数模上给定的一个数是多少?

    分析:首先这些数互质时,最小公倍数最大,考虑到素数都是互质的,猜想可能都被拆分成了素数,

    证明:假设这些数被拆分成了m1+m2+m3+...+mk;除mk是合数外其余数都是素数,

    mk可以写成一个素数和另外一个数的乘积,mk=a*b,所求的最大的最小公倍数就是m1*m2*m3*...*mk;

    然而由于a+b<a*b;将mk分成a+b+(mk-(a+b)),得到的结果肯定比直接加上mk要大,

    所以就证明了这些数都为素数。

    证明 a+b<a*b;

      1 < (a-1)(b-1);(a>1 && b>1)

      1 < a*b-a-b +1;

          a+b+1 < a*b+1   ;

    注意到这些素数的乘积可能特别大,所以两边同时去ln,变成加法;

    #include <iostream>
    #include <cstdio>
    #include <cstring >
    #include <cstdlib>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    #define  maxn 3100
    int prime[maxn];
    double d[maxn];
    int ans[maxn];
    int vis[maxn];
    int n,MOD;
    void init()
    {
       memset(ans,0,sizeof(ans));
       memset(d,0,sizeof(d));
    }
    int pow(int a,int b)
    {
        int answer=1;
        for(int i=1;i<=b;i++)
            answer*=a;
        return answer;
    }
    void solve()
    {
        for(int j=0;j<=n;j++)
        {
             d[j]=0;
             ans[j]=1;
        }
        for(int i=2;prime[i]<=n;i++)
        {
             for(int j=n;j>=0;j--)
            {
                for(int k=1;pow(prime[i],k)<=j;k++)
                //对于第k个素数,有两种选择
                {
                    int s=pow(prime[i],k);
                    if(j>=s)
                    if(d[j-s]+log(s*1.0) > d[j] )
                    {
                        d[j]=d[j-s]+log(s*1.0);
                        ans[j]= ( (ans[j-s]*s) )%MOD;
                    }
                }
                //printf("%d ",ans[j]);
            }
           // printf("
    ");
        }
        printf("%d
    ",ans[n]);
    }
    int main()
    {
        //cout<<log(2.718281828459)<<endl;
        int N=maxn-1;
        int m=sqrt(N+0.5);
        memset(vis,0,sizeof(vis));
        for(int i=2;i<=m;i++)
            if(!vis[i])
            for(int j=i*i;j<=N;j+=i)
                vis[j]=1;
        int t=1;
        for(int i=1;i<=N;i++)
            if(vis[i]==0)
             prime[t++]=i;
       /* for(int i=1;i<10;i++)
        {
            printf("%d ",prime[i]);
        }*/
        //cout<<endl;
        while(~scanf("%d%d",&n,&MOD))
        {
           init();
           solve();
        }
        return 0;
    }

       

        

  • 相关阅读:
    【转】将项目打成war包并用tomcat部署的方法,步骤及注意点
    JETTY+NGINX
    【转】收集 jetty、tomcat、jboss、weblogic 的比较
    SQL左右连接中的on and和on where的区别
    定义一个servlet用于处理所有外部接口类 架构思路
    spring上下文快速获取方法
    jasper打印实例2 ----通过文件字节流获得PDF格式图片
    Jasper打印示例
    Jasperreport5.6.9-----1
    Linux装B命令
  • 原文地址:https://www.cnblogs.com/xianbin7/p/4819491.html
Copyright © 2011-2022 走看看