TJU-4107. A simple problem(贪心)

Given three integers n(1n1018) , m(1m105) , k(1k1018) . you should find a list of integer A1,A2,,Am which satisfies three conditions:
1. A1+A2++Am=n .
2. 1Aik1 for each (1im) .
3. GCD(A1,A2,,Am)=1 .GCD means the greatest common divisor
4. if i<j then AiAj .

As the author is too lazy to write a special judge, if there's no answer ouput "I love ACM", And if there's more than one answer, output the one has the minimum A1 , and if there still multiple answer make the A2 as small as possible, then A3,A4


主要思想:

把n先均分成m份,多余的分摊到前面。如果数列存在两个相差1的数,那么这个数列整体的GCD为1.

这里有好多特殊情况要处理,比如m=1,m=2,n=m等等等。

比如

10 2 10

10 10 3

10 5 3

2 1 2

1 1 3

ps:TJU的数据很弱,队友丢了情况都过了......

自己有一处判断加上去之后就WA,不知道为什么。

#include<cstdio>
#include<cstring>
#define imp {printf("I love ACM\n"); return;}
using namespace std;

long long ans[100005];

long long gcd(long a,long b)
{
    long long r;
    while(b>0)
    {
        r=a%b;
        a=b;
        b=r;
    }
    return a;
}

void work(long long n,long long m,long long k)
{
    int i,j;
    long long x,y;

   // if((m*k-m)<=n)
   //实在搞不懂为什么加上上面那句话就会WA
    if(n<m) imp
    if(n==m)
    {
        if(k<2) imp
        else
        {
            printf("1");
            for(i=2;i<=m;i++) printf(" 1");
            printf("\n");
            return ;
        }
    }
    if(m==1)
    {
        if(n!=1) imp
        if(k<=1) imp
        printf("%lld\n",n);
    }
    else if(m==2)
    {
        if((n&1)==0)
        {
            x=y=n/2;
            x++;
            y--;
            while(gcd(x,y)!=1 && x<k && y>0)
            {
                x++;
                y--;
            }
            if(gcd(x,y)!=1) imp
            if(x>=k) imp
            printf("%lld %lld\n",x,y);
        }
        else
        {
            x=y=n/2;
            x++;
            if(gcd(x,y)!=1) imp
            if(x>=k) imp
            printf("%lld %lld\n",x,y);
        }
    }
    else
    {
        for(i=1;i<=m;i++) ans[i]=n/m;
        if(n%m==0)
        {
            ans[1]++;
            ans[m]--;
            if(ans[1]>=k) imp
            for(i=1;i<m;i++) printf("%lld ",ans[i]);
            printf("%lld\n",ans[m]);
        }
        else
        {
            n-=ans[1]*m;
            i=0;
            while(n--) ans[++i]++;
            if(ans[1]>=k) imp
            for(i=1;i<m;i++) printf("%lld ",ans[i]);
            printf("%lld\n",ans[m]);

        }    
    
    }

}
int main()
{
    long long n,m,k;
    while(~scanf("%lld%lld%lld",&n,&m,&k))
        work(n,m,k);
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值