链接:https://ac.nowcoder.com/acm/contest/8282/A
来源:牛客网
题目描述
蒟蒻 brz 有 n 只杯子,现在 lzyking 拿了一些数字,要求蒟蒻 brz 装到杯子里。
lzyking 拿了 1 ~ m 这些数字,每个数字有无限个,但每个杯子里只能放一个数。lzyking 很挑剔,对于两个编号为 x,y 的杯子,假如满足 y|x(y能够整除x)y!=x,那么第 x 个杯子里的数一定要比第 y 个杯子里的大。
但是小蒟蒻 brz 不知道到底存不存在一个放数字的方案,所以只好求助于你。
输入描述:
第一行一个整数,表示有T次询问。
每组询问内有两个整数n,m,意<如上所述。
1 <=T <=10^6,1<= n,m<= 10^9
输出描述:
对于第 i 个询问,如果存在一个放数字的方案,那么贡献为 i,否则为 i-1,令 ans 等于所有询问的贡献异或和,最后你只需要输出 ans 即可。
示例1
输入
复制
2
3 3
2 1
输出
复制
0
说明
对于第一组样例,可以在第一个杯子里放 1,在第二个杯子里放 2,在第三个杯子里放 3,贡献为 1。
对于第二组样例,在第一个杯子里放 1 后,由于第二个杯子里的数要比第一个杯子里的数大,但是又没有比 1 大的数可以放了,所以不存在一种方案,贡献为 2-1=1。
答案为 1 xor 1=0。
分析:
假设每个杯子装的是符合要求的最小的数字,对于每个样例,只需要找到装着最大数字的杯子,如果这个数字<=m,则存在方案,否则不存在。
从1-20,写了一下杯子最小能装的数字,发现编号是2^ i的杯子总是装着数字x的第一个杯子,所以只需要比较1-n最大的2^i的i与m的大小。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e6+10;
int a[N];
int main()
{
int T;
int ans=0;
scanf("%d",&T);
for(int z=1;z<=T;z++)
{
int n,m;
scanf("%d %d",&n,&m);
int t,x=1;
for(int i=1;;i++)
{
x=x*2;
if(x>n)
{
t=i;
break;
}
}
if(t<=m) ans=ans^z;
else ans=ans^(z-1);
}
printf("%d",ans);
return 0;
}