P4932 浏览器
P4932 浏览器
题目背景
__stdcall在用Edge玩slay的时候,鼠标会经常失灵,这让她十分痛苦,因此她决定也要让你们感受一下Edge制造的痛苦。
题目描述
__stdcall给了你n个点,第i个点有权值x[i],对于两个点u和v,如果x[u] xor x[v]的结果在二进制表示下有奇数个1,那么在u和v之间连接一个Edge,现在__stdcall想让你求出一共有多少个Edge。
如果你没能成功完成任务,那么__stdcall会让你痛苦一下,你这个测试点就没分了。
STL bitset
bitset 是 STL中性能优良的二进制载体, 优点在之前某篇博客说过了这里不再赘述
我只是想说 bitset快 !!! 牛逼 !!
这里说说 bitset 的赋值
实验发现 \(unsigned\ long\) 类型的数赋值给 \(bitset\) 要比 \(int\) 类型快, 防止出错以后都用 \(unsigned\ long\) 吧
unsigned long x;
bitset<32>a(x);//初始赋值
int main(){
a = x;//直接赋值
}
Solution
失态失态
由于自带状态压缩, bitset 无论在执行位运算还是运行其中的函数都展现出很高的效率, 很厉害
打表找规律无解(from __stdcall)
我们记popcnt(x)表示x在二进制表示下1的个数。
观察之后不难发现,popcnt(a xor b)的奇偶性和popcnt(a)与popcnt(b)的奇偶性有关系。
具体来说,当popcnt(a)和popcnt(b)是一奇一偶的时候,popcnt(a xor b)是奇数,否则就是偶数。
因此,我们只需要统计每个点的权值的popcnt,用奇数的个数乘以偶数的个数就是答案。
然而 \(O(nlogv)\) 并不能过掉本题, 所以采用 \(count[bitset]\)
最后注意, bitset 函数运算速度与其大小成正比
Code
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#include<climits>
#include<bitset>
#define LL long long
#define REP(i, x, y) for(LL i = (x);i <= (y);i++)
using namespace std;
LL RD(){
LL out = 0,flag = 1;char c = getchar();
while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
return flag * out;
}
LL odd, eve;
LL n, a, b, c, d, x0;
bitset<32>x;
void work(LL n){
REP(i, 1, n){
x0 = (((a * x0 % d * x0 % d) + (b * x0 % d) + c) % d + d) % d;
x = x0;
LL cnt = x.count();
if(cnt & 1)++odd;
else ++eve;
}
printf("%lld\n", odd * eve);
}
int main(){
n = RD(), a = RD(), b = RD(), c = RD(), d = RD(), x0 = RD();
work(n);
return 0;
}