将正整数n分解为m个互不相同/相同/m个不同的自然数之和,使这些自然数的乘积最大

  • 不相同

 前一阵子做的牛客网的一个题【题目链接】戳进来 

 找规律或者贪心

 规律 : a[4]=a[1]+a[3],a[5]=a[4]+a[2],a[6]=a[4]+a[2],a[7]=a[6]+a[4],a[8]=a[7]+a[5],a[9]=a[8]+a[5],写出来你就发现每三个有个特殊的,嗯,就是这样的,不要怀疑。

#include<iostream>
using namespace std;
typedef long long ll;
ll ans[2005];
const ll mod=2000000000000000003;
void init()
{
    ans[1]=1,ans[2]=2,ans[3]=3;
    int t=0;
    for(int i=4;i<2005;i++)
    {
         if(t==3)
         {
             t=0;
             ans[i]=(ans[i-1]+ans[i-4])%mod;
         }
         else
         {
             ans[i]=(ans[i-1]+ans[i-3])%mod;
         }
         t++;
    }
}
int main()
{
    init();
    int T;
    cin>>T;
    while(T--)
    {
        int x;
        cin>>x;
        cout<<ans[x]<<endl;
    }
    return 0;
}

贪心:元素相连,尽可能均分元素,如果往后有剩余,从后往前每个多分个1

#include<iostream>
#include<vector>
using namespace std;
int main(){
    int num;
    while(cin>>num){
        int flag[100] = {0};
        int k=2;
        int i=0;
        while(num >= k){
            flag[i++] = k;
            num -= k;
            k++;
        }
        if(num > 0){
            if(num == flag[i-1]){
                flag[i-1]++;
                num--;
            }
            for(int j=i-1;j>=0 &&num>0;j--){
                flag[j] ++;
                num--;
            }
 
        }
        int result = 1;
        for(int j = 0;j<i;j++){
            result *= flag[j];
        }
        cout<<result<<endl;
    }
    return 0;
}

  • 可以相同的

尽可能的分3,如果不能分3就分离个2出来

#include<iostream>
#include<math.h>
using namespace std;
int main(){
    int num;
    while(cin>>num){
        if(num % 3 == 0){
            cout<<pow(3,num/3)<<endl;
            continue;
        }
        int flag[100] = {0};
        int i=0;
        while(num != 2 && num != 4){
            //如果不能被3整除,那么除3必余1或者2,而余1和4是同样的情况,这里取4是因为这种情况下最后是两个2,
            //取4就可以直接把4分解为2+2
            flag[i++]=3;
            num-=3;
        }
        while(num){  //余2和1的情况,余2就是1个2,余1就是2个2,所以前面才会判断是否等于4,这样就可以化为2个2
            flag[i++] = 2;
            num-=2;
        }
        int result = 1;
        for(int j=0;j<i;j++){
            result *= flag[j];
        }
        cout<<result<<endl;
    }
    return 0;
}
  • m个不相同

与互不相同类似,贪心解决。

#include<iostream>
using namespace std;
int test(int x,int y)
{
    if((y+y*y)>(2*x))
        return 0;
    else
        return 1;
}
void slove(int x,int y)
{
    int flag[1000],index=1,k=2;
    while(x>=k)
    {
        flag[index++]=k;
        x-=k;
        k++;
        if(index-1==y)
            break;
    }
    if(index==y&&x!=0)
    {
        flag[index]=1;
        x--;
        while(x!=0)
        {
            for(int j=index;j>=1&&x!=0;j--)
            {
                flag[j]++;
                x--;
            }
        }
        long long ans=1;
        for(int i=1;i<=index;i++)
            ans*=flag[i];
        cout<<ans<<endl;
    }
    else
    {
        index--;
        while(x!=0)
        {
            for(int j=index;j>=1&&x!=0;j--)
            {
                flag[j]++;
                x--;
            }
        }
        long long ans=1;
        for(int i=1;i<=index;i++)
            ans*=flag[i];
        cout<<ans<<endl;
    }
}
int main()
{
    int n,m,t;
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        if(test(n,m)==0)
            cout<<-1<<endl;
        else
            slove(n,m);
    }
    return 0;
}

详细看这个大佬的博客戳进来,我只是小白,代码写的有错误的地方,请指出。

猜你喜欢

转载自blog.csdn.net/jdq8576/article/details/80554139