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("\n");
    }
    printf("%d\n",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;
}

 

   

    

 

posted on 2015-09-18 16:05  爱装逼的书呆子  阅读(495)  评论(0编辑  收藏  举报

导航