2020.1.7 校内测试 T1 分火腿

题目链接  https://www.luogu.com.cn/problem/U101928

看了一眼觉得 T1 很水,原来是我想错了,悲惨爆零qwq。 虽然确实挺水的

嗯,首先看一下题目中的一个细节:

将 n 根火腿分成均等的 m 份不是 m 段 我就死在了这里 

也就是说,你可以把两个火腿分成:2/3,1/3,1/3,2/3 四段,其中第二段和第三段可视为一份!

题解

既然如此,我们干脆把 n 根火腿看成一大根好了;

如果我们假设每根火腿的长度为 1,那么这根大火腿的长度为 n;

我们要将其分成均等的 m 份,那么每一份的长度就都是 n/m;

考虑到我们砍一刀就多一段,那么我们最多需要砍 m-1 刀;

还需要注意一个地方:

这 m-1 刀中有若干刀可能就是火腿的接口,也就是说本来这个地方就是断开的,只不过是我们人为的看成是一段而已,但是我们却花费了 1 刀把它切开。

所以我们只需再找出这 m-1 刀中有多少刀正好砍在了两根火腿的接口处,用 m-1 一减就是最后答案了。

可以想到既然有一刀砍在了两根火腿的接口出,那么前面分成的若干段长度为 n/m 的分拼起来可以组成若干根完整的火腿;

也就是说这个接口处必须同时满足是每一根火腿的长度(1)每一份长度的倍数(n/m) 的倍数,还得是正整数;

因为前面的若干份是由若干根完整的火腿切来的,必须保证同时是它俩的整数倍数;

那么我们就先要求出 lcm ( 1,n/m )来 。

设 k = lcm ( 1,n/m ) = lcm ( m,n ) / m = m * n / gcd ( n,m ) / m = n / gcd ( n,m )

那么这个长度为 n 的大火腿中有 n / k = n / ( n / gcd ( n,m ) ) = gcd ( n,m ) 个 k 的倍数,也就是有这么些个接口符合要求;

但是由于 n 也是 k 的倍数,所以我们把最后一刀(砍在了长度为 n 的大火腿的末端的那一刀)给算上了,实际上是不需要的,那么需要减一,也就是:

gcd ( n,m ) - 1

最后我们再用 m-1 一减,就是最后的答案了:

Ans = ( m - 1 ) - ( gcd ( n,m ) - 1 ) = m - gcd ( n,m )

那么我们直接输出 m - gcd ( n,m ) 就大功告成了!

Code:

#include<iostream>
#include<cstdio>
using namespace std;
int T,n,m;
int gcd(int a,int b)
{
    if(b==0) return a;
    return gcd(b,a%b);
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        printf("%d\n",m-gcd(n,m));
    }
}

猜你喜欢

转载自www.cnblogs.com/xcg123/p/12165828.html