POJ 3902 The Bad Number(贪心)

142 篇文章 0 订阅

Description
给出三个整数n,m,k,要求你需要把m拆成最少的x个数之和,需要满足x不被n整除,每个数不被n整除且不超过k,输出x
Input
第一行为一整数T表示用例组数,每组用例占一行包括三个整数n,m和k
Output
对于每组用例,输出x,如果不存在满足条件的方案则输出-1
Sample Input
2
3 11 6
2 12 47
Sample Output
4
-1
Solution
容易得到贪心思路就是尽可能贪心的让这x个数接近k,但各种特殊情况均需要特判,详细见代码
Code

#include<stdio.h>
int main()
{
    int t,n,m,k;
    scanf("%d",&t);
    while(t--)
    {
        int ans=0,res;
        scanf("%d%d%d",&n,&m,&k);
        if(n==1)//n=1时显然不成立 
        {
            printf("-1\n");
            continue;
        }
        if(k==1)//k=1时m必须被拆成m个1 
        {
            if(m%n)printf("%d\n",m); 
            else printf("-1\n");
            continue;
        }
        if(n==2)//n=2时m需要被拆成奇数个奇数之和 
        {
            if(m%n==0)printf("-1\n");//m为偶数不成立 
            else//m为奇数 
            {
                if(k%2==0)k--;//k是偶数就减一 
                ans=m/k;//尽可能拆成k,显然ans为奇 
                res=m%k;//显然res为奇 
                if(res)
                {   
                    ans++;//余数不为0 
                    if(ans%2==0)ans++;//ans此时为偶则需要从前ans-1个数中分别拿出1组成第ans+1个数 
                } 
                printf("%d\n",ans);
            }
            continue;
        }
        if(k%n==0)k--;//k%n=0则k减一以满足尽可能拆成k且数不会整除n的条件 
        ans=m/k;//尽可能拆成k 
        res=m%k;
        if(res==0)//余数为0 
        {
            if(ans%n==0)ans++;//ans为n的倍数则将最后一个k拆成两个不是n倍数的数 
            printf("%d\n",ans);
        }
        else
        {
            ans++;//余数不为0则需要多一个数来放余数 
            if(ans%n==0)ans++;//ans为n的倍数则将余数拆成两个不是n倍数的数即可 
            else//ans不是n的倍数,判断是否需要多拆一个数以满足条件 
            {
                if(res%n==0)//余数是n的倍数 
                {
                    if(ans==1)ans++;//ans=1说明m<k,此时只需将m拆成两个不是n倍数的数即可 
                    else if((k-1)%n==0)//此时需判断是否能通过将最后一个k和res分成两个满足条件的数 
                    {
                        int flag=0;
                        for(int i=2;i<n&&i+res<k&&i<k;i++)//枚举 
                            if((k-i)%n!=0&&(i+res)%n!=0)//找到满足条件的值 
                            {
                                flag=1;
                                break;
                            }
                        if(!flag)//不存在满足条件的值,那么就需要将res拆成两个不是n倍数的数 
                        {
                            ans++;
                            if(ans%n==0)ans++;//ans是n的倍数就将其中一个k拆成两个不是n倍数的数 
                        }
                    }
                }
            }
            printf("%d\n",ans);
        }
    }
    return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值