1024 (程序员节) 欢乐赛 T1 分火腿 (思路题)

题面:

分火腿

hdogs.pas/.c/.cpp

时间限制:1s;内存限制 64MB

题目描述:

小月言要过四岁生日了,她的妈妈为她准备了n根火腿,她想将这些火腿均分给m位小朋友,所以她可能需要切火腿。为了省事,小月言想切最少的刀数,使这n根火腿分成均等的m份。请问最少要切几刀?

输入描述:

第一行一个整数T,表示有T组数据。

接下来T组数据,每组共一行,有两个数字nm

输出描述:

每组数据一行,输出最少要切的刀数。

样例输入:

2

2 6

6 2

样例输出:

4

0

数据范围:

100%的数据保证T<=1000n,m<=2147483647

  不得不说,这道题,我确实没看懂……只有特判一下,输出0骗分滚粗QAQ

  试(事)♂后,才发现其实超级简单啊……

  思路如下:

  我们把这些火腿看成是一根大火腿,不过一些位置已经被切过了。

  根据题意,我们要把这根大火腿平均切。既然如此,那我们每次切的位置一定是确定的,并且切了m-1刀。

  这样,我们需要做的就是判断一下那些位置已经被切过了,不需要我们再切,再将这些位置有几个记录一下,最后减去就好了。

  可以想象,那些需要切的位置与已经切好的位置重合的条件就是此时需要切的位置需要切的长度已经切好的长度的位置的最小公倍数的整数倍。(需要切的长度就是平分后的每个人得到长度,已经切好的长度就是每根火腿的长度)

  设每根火腿长度为1,则平分后每个人得到的长度是n/m(n根火腿,m个人),设最小公倍数为k。那么1与n/m的最小公倍数k=(n*m/gcd(n,m))/m=n/gcd(n,m)。(这是分数的最大质因子求法https://zhidao.baidu.com/struct/questions/fedf07371bcd1c35ac8977b0.html那么重合被切的位置就有(n/k)个,也就是(gcd(n,m)-1)个。(注意:这里减一的原因是我们把最后一个也算进去了,也就是这根大火腿的尾端。被算进去的原因也很简单,尾端是一定能被我们恰好切的,因为n一定是1和(n/m)的公倍数。至于为什么首端为什么没有被算进去是因为0不是1和(n/m)的公倍数。)

  那么只要输出m-1-(gcd(n,m)-1)=m-gcd(n,m)就好啦~

  代码如下:

 

#include<bits/stdc++.h>
using namespace std;
int n,m,T;
template<class T>inline void read(T &x)
{
    x=0;int f=0;char ch=getchar();
    while(ch<'0'||ch>'9'){ f|=(ch=='-'); ch=getchar(); }
    while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
    x=f ? -x:x;
    return;
}
inline int Gcd(int x,int y)
{
    int c=x%y;
    while(c!=0)
    {
        x=y;
        y=c;
        c=x%y;
    }
    return y;
}
int main()
{
//    freopen("hdogs.in","r",stdin);
//    freopen("hdogs.out","w",stdout);
    read(T);
    while(T--)
    {
        read(n);read(m);
        if(n%m==0)printf("0\n");//特判
        else printf("%d\n",m-Gcd(n,m));
    }
//    fclose(stdin);
//    fclose(stdout);
    return 0;
}

 

转载于:https://www.cnblogs.com/Wujiga/p/7723687.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值