思维+二进制数brz的杯子
解题思路
这我是真没想到题目的 y ∣ x y∣x y∣x 意思是 x x x 可以被 y y y 整除…
那么问题意思就是:第 x x x 个杯子里的数要比它的因子 y y y 对应的杯子里的数大。
可以举个例子,比如现在 n n n 是 9 9 9。
如果 x x x 是 8 8 8,因子有 2 , 4 2, 4 2,4,假设编号 1 1 1 的杯子里放的数是 1 1 1(从最小的开始枚举),那么编号 2 , 4 , 8 2, 4, 8 2,4,8 的杯杯就得分别放 2 , 3 , 4 2,3,4 2,3,4。
如果 x x x 是 9 9 9,因子有 3 3 3,那么编号 3 3 3 的杯杯要比编号 1 1 1 的杯的数大,所以放 2 2 2。
从上面的分析可以看出,至少需要 4 4 4 个数,所以 m > = 4 m >= 4 m>=4 就满足条件了。
我们只要去找 2 2 2 的次方的个数就行了。我做的时候是去找不大于 n n n 的 2 i 2^i 2i,统计个数,与 m m m 比较即可。
之后看了别人的题解,发现可以更简单,即判断 n n n 二进制的位数。妙啊~
参考代码
#include<bits/stdc++.h>
using namespace std;
//#define LOCAL //提交的时候一定注释
#define _for(i, a, b) for(int i = (a); i < (b); ++i)
#define _rep(i, a, b) for(int i = (a); i <= (b); ++i)
#define pb push_back
#define VI vector<int>
#define INF 0x3f3f3f3f
#define mp make_pair
typedef long long LL;
typedef double db;
const double eps = 1e-6; //定义浮点数误差
const int MOD = 998244353;
const LL maxn = 1e9 + 10;
int readint(){
int x; scanf("%d", &x); return x;
}
int main() {
#ifdef LOCAL
freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
#endif
int t, ans, n, m;
scanf("%d", &t);
bool flag = false; //flag记录是否是进行第一个查询
_rep(i, 1, t) {
scanf("%d%d", &n, &m);
int cnt = 0;
bool yes = true; //yes记录是否能有方案
for(int j = 1; (j << 1) <= n; j <<= 1) cnt++; //统计需要的数字个数,从j=1开始,包括了编号为1的杯子
if (cnt >= m) yes = false;
if (!flag) {
//第一个查询结果先保存,之后直接计算异或和
ans = yes ? i : i - 1;
flag = true;
}
else
ans ^= (yes ? i : i - 1);cpp
}
printf("%d", ans);
return 0;
}