(纪中)2216. greatest【DP+高精】

(File IO): input:greatest.in output:greatest.out
时间限制: 1000 ms 空间限制: 131072 KB 具体限制
Goto ProblemSet


题目描述
已知若干个正整数的和为 S S ,求这若干个正整数的最小公倍数的最大值。


输入
第一行一个整数 T T ,表示测试数据的组数。
接下来 T T 行,每行包括一个正整数 S S ,表示若干个正整数的和为 S S

输出
输出 T T 行,每行包括一个整数,表示和为 S S 的若干个正整数的最小公倍数的最大值。


样例输入
2
4
7

样例输出
4
12


数据范围限制
样例中第一组数据 S = 4 S=4 ,它能分解成 S = 1 + 1 + 1 + 1 S = 1 + 1 + 2 S = 1 + 3 S = 2 + 2 S = 4 S=1+1+1+1,S=1+1+2,S=1+3,S=2+2,S=4 ,很明显 S = 4 S=4 时最小公倍数为 4 4 ,是所有情况中最小公倍数最大的;第二组数据 S = 7 S=7 ,它能分解成 S = 3 + 4 S=3+4 3 3 4 4 的最小公倍数是 12 12 ,也是所有情况中最小公倍数最大的。


提示
40 40 %的数据: S 100 S≤100
80 80 %的数据: S 330 S≤330 ,结果不会超过 l o n g l o n g long long 类型;
100 100 %的数据: 2 S 500 T 10 2≤S≤500,T≤10 ,结果不会超过 25 25 位整数。


解题思路
心路历程:
开始看题
嗯……压根想不出任何方法。。。
再留意数据范围,我 (哔——),满分还要高精度?
(弃疗中………………)。。
最后膜拜巨老 l z h lzh 。。。 21 : 45 21:45 分竟然过了。。

好吧,回归正题。。
首先我们明白,两个数的乘积等于两个数的最小公倍数乘最大公约数,
其次,我们还能想到,只要两个数所拥有的质因数不同,那么最大公约数也就很小,反之最大公约数就很大!!
(证明:x1+y1<x1*y1(2<=x1,y1),我们就可以分解质因数)
我们可以把题目变成一个背包问题
S S 是背包的总容量,每个质因数和它的次幂都是一件物品,这些物品重量是它本身,价值是它本身乘原来的价值,
我们再根据上面所说的,两个数所拥有的质因数要不一样,所以,一个质数的次幂只能取一个。。

动态转移方程: f [ i ] = m a x f [ i j k ] j k ( j k < = i ) f[i]=max{f [ i - j ^ k ] * j ^ k}(j ^ k<=i)
(下面附上我那很长的代码)


代码

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cmath>
using namespace std;
int t,n,zs[600],m,a[600][50],s,p,c[50];
bool flag;
void ch(int x,int y)
{
    memset(c,0,sizeof(c));
    int g=0;
    for(int i=49; i>=1; i--)
    {
        c[i]=a[x][i]*y+g;
        g=c[i]/10;
        c[i]%=10;
    }
}
bool hh(int x)
{
    int i=1;
    while(a[x][i]==0)i++;
    i=49-i;
    int j=1;
    while(c[j]==0)j++;
    j=49-j;
    if(i>j)return 0;
    if(j>i)return 1;
    for(int ii=i; ii<=49; ii++)
    {
        if(a[x][ii]>c[ii])return 0;
        if(c[ii]>a[x][ii])return 1;
    }
}
int main()
{
      freopen("greatest.in","r",stdin);
   freopen("greatest.out","w",stdout);
    for(int i=2; i<=501; i++)
    {
        flag=1;
        for(int j=1; j<=t; j++)
        {
            if(i%zs[j]==0)
            {
                flag=0;
                break;
            }
        }
        if(flag==1)
        {
            zs[++t]=i;
        }
    }
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
    {
        scanf("%d",&m);
        memset(a,0,sizeof(a));
        for(int i=0; i<=m; i++)
            a[i][49]=1;
        for(int j=1; j<=t; j++)
        {
            for(int i=m; i>=1; i--)
            {
                s=zs[j];
                for(int k=1; s<=i; s*=zs[j])
                {
                    ch(i-s,s);
                    if(hh(i))
                    {
                        for(int q=1; q<=49; q++)
                            a[i][q]=c[q];
                    }
                }
            }
        }
        p=1;
        while(a[m][p]==0)p++;
        while(p<=49)
        {
            cout<<a[m][p];
            p++;
        }
        cout<<endl;
    }
    return 0;
}
发布了119 篇原创文章 · 获赞 8 · 访问量 4926

猜你喜欢

转载自blog.csdn.net/kejin2019/article/details/104705084
今日推荐