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;
}