#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 2e5 + 5, inf = 1e18;
int a[maxn];
int suf[maxn];
string s;
int n, m;
map<int, int> mp;
int calc(int x, int m, int mm){
if(x == 0 || mm == 0) return 0;
int sum = 0;
int now = m;
int last = __lg(m);
for(int j = 31; j >= 0; j--){
if(x >> j & 1){
sum += last - j;
last = j;
}
}
// cout << x << ' ' << mm << ' ' << sum * (mm + 1) / 2 << '\n';
return (mm + 1) / 2 * sum + calc(x - (x & -x), m, mm - (mm + 1) / 2);//!!!!先算(mm + 1) / 2!!!!!!
}
void solve()
{
cin >> n >> m;
int gcd = __gcd(n, m);
int mm = m, nn = n;
n /= gcd;
m /= gcd;
if(((m - 1) & m) != 0){
cout << "-1\n";
return;
}
n = n % m;
int res = 0;
for(int j = 31; j >= 0; j--){
if(n >> j & 1){//把n分解为二进制,先集中把每个2^j分别切完是最优的,
//因为每个2^j都要mm个,又因为m是2的幂次,所有2^j整除m,并且恰好用整数个m切完。
int pw = (1LL << j);
res += mm / (m / pw) * (m / pw - 1);//必须用除以gcd的m,n来做,反例:1 117 18 答案:9
}
}
cout << res << '\n';
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int T = 1;
cin >> T;
while (T--)
{
solve();
}
return 0;
}
有n条长度为1的棍子,每次只能把棍子切成长度相同的两半,求把n条棍子平均分给m个人最少要切几次
最新推荐文章于 2025-12-22 09:47:08 发布
该篇文章介绍了如何使用C++编程解决一个计算问题,给定整数n和m,找到n在模m下的最优二进制切分次数,使得每个2的幂次整除m且恰好用整数个m切完。涉及了位操作和整数除法等技巧。
2133

被折叠的 条评论
为什么被折叠?



