zoukankan      html  css  js  c++  java
  • noip欢乐赛10.24 分火腿

    分火腿

    题目描述:

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

    输入描述:

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

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

    输出描述:

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

    样例输入:

    2

    2 6

    6 2

    样例输出:

    4

    0

    数据范围:

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

    蒟蒻吐槽:

      一道奇奇怪怪的数学题吧?貌似。题目可以分为两种情况,n>m或者n<m,但其实,在n>m的情况中,把多余的火腿直接整个分给其他人就可以了。所以n-=n/m*m。然后就变成了n<m的情况了。在n<m中,可以把n根火腿看成一根大火腿,在1/n.2/n,3/n···

    n-1/n处已经被切过了,而为了平均分配,我们要在1/m,2/m,3/m···m-1/m处再次切割,所以我们只需要求二者交集,交集是我们可以偷懒的刀数,而我们总共要砍m-1刀。

    以上就是对这道题的感性认知。

      重要的理性思维到来了!虽然很烦,但这是历史的必然啊!已经被切过的刀位置定义为p/n,需要的刀定义为q/m。通分得pm/mn和qn/mn,二者交集等价于pm=qn,从p=n,q=m出发易得p,q同时除以gcd(m,n)后,等式才可以继续成立,又因为p和q中较小的是p所以交集个数受n限制,即个数=(n-1)/gcd(n,m)。为什么要减一呢?注意了,p<=n-1所以ans=m-1-(n-1)/gcd(n,m)。顺便附上代码。

    代码

    #include<cstdio>
    
    int gcd(int a,int b)
    {
        int r=a%b;
        while(r!=0)
        {        
            a=b;
            b=r;
            r=a%b;
        }
        return b;
    }
    int main()
    {
        freopen("hdogs.in","r",stdin);
        freopen("hdogs.out","w",stdout);
        int T,a,b,x,ans;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&a,&b);
            if(a%b==0){printf("0
    ");continue;}
            a=a-b*(a/b);
            x=gcd(a,b);
            x=a/x;
            ans=b-1-(a-1)/x;
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    【poj1733】 Parity game
    【poj1018】 Communication System
    【poj1017】 Packets
    【poj1568】 Find the Winning Move
    【poj1085】 Triangle War
    【bzoj1082】 SCOI2005—栅栏
    【codevs1086】 栈
    【bzoj3240】 Noi2013—矩阵游戏
    【bzoj1951】 Sdoi2010—古代猪文
    中国剩余定理学习笔记
  • 原文地址:https://www.cnblogs.com/mofangk/p/7725549.html
Copyright © 2011-2022 走看看