codeforces 1875C

本题涉及gcd,lcm以及判断某数是否为2的整数次幂

思路

先令 n = n % m n=n\%m n=n%m,先把n平均分了,缩小计算范围,则现在n严格小于m
把n均分给m,则共需 l c m ( n , m ) lcm(n,m) lcm(n,m)
l c m ( n , m ) lcm(n,m) lcm(n,m) = n ∗ m / g c d ( n , m ) =n*m/gcd(n,m) =nm/gcd(n,m)
则每个人被分给 x = n / g c d ( n , m ) x=n/gcd(n,m) x=n/gcd(n,m)片,则每个果子被分成 y = m / g c d ( n , m ) y=m/gcd(n,m) y=m/gcd(n,m)
因为一刀把一个分成两个,所以y一定是2的整数次幂
题目中是考虑切几刀,我们这里可以逆向思考,有几个相同的片合在一起就是几刀
所以我们是求x的二进制表示有几个1,这里可以用stl里的__builtin_popcount(),直接算出来x的二进制表示里有多少个1,也可以用个while

ACcode

#include

using namespace std;

using ll = long long;

void solve() {
    ll n, m;cin >> n >> m;
    if (n % m == 0) {
        cout << 0 << '\n';
        return;
    }
    n %= m;
    ll lc = 1ll * n * m / __gcd(n, m);
    ll x = 1ll * lc / m;//每个人
    ll y = 1ll * lc / n;//每个果
    ll t = y & -y;
    if (t != y) {//可以用 n&-n == n 来判断n是不是2的整数次幂
        cout << -1 << '\n';
        return;
    }
    int cnt = 0;
    //cnt = __builtin_popcount(x);
    while (x) {
        if (x & 1)cnt++;
        x /= 2;
    }
    cout << 1ll * cnt * m - n << '\n';
}

int main() {
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int t;cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}

你可能感兴趣的:(算法,c++)