P4932 浏览器 题解
简要题意:
给定 \(n\) 个点的权值 \(x_i\),求 \(u \not = v\) 且 \(x_u \space \text{xor} \space x_v\) 有奇数个 \(1\) 的个数。
算法一
对于前 \(60 \%\) 的数据,\(n \leq 1000\).
很简单啊,直接枚举两个点,然后 \(\text{xor}\) 一下就可以了。
时间复杂度:\(O(n^2)\).
实际得分:\(60pts\).
算法二
对于前 \(80 \%\) 的数据,\(n \leq 10^6\),\(v \leq 10^6\).(\(v = \max_{i=1}^n x_i\))
显然,我们考虑 \(\text{xor}\) 的性质。
\(\text{xor}\) 如果两位相同则为 \(0\),否则为 \(1\);它不会改变 两个数 \(1\) 的个数之和,因为 \(1\) 要么两个两个被计算掉,要么一个个被保留。
所以,用 \(f_i\) 表示 \(x_i\) 二进制下 \(1\) 的个数,本题变为:
求 \(f_i + f_j\) 为奇数的个数,这个统计奇偶就可以了。
关键如何统计二进制下 \(1\) 的个数?暴力转进制即可。
时间复杂度:\(O(n \log v)\).
实际得分:\(80pts\).
算法三
优化求 \(1\) 的个数的过程即可。
可以用 \(\text{\_\_builtin \_parity}\) 优化(\(\text{CSP / NOIP}\) 不支持啊),不过手测 \(O(n \log v)\) 过了。
时间复杂度:\(O(n)\).
实际得分:\(100pts\).
// tot[__builtin_parity(x=((a*x%d)*x%d+b*x%d+c)%d)&1]++; 等同于:
// x=((a*x%d)*x%d+b*x%d+c)%d;
// tot[__builtin_parity(x)&1]++;
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read(){char ch=getchar();int f=1;while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
ll x=0;while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;}
ll n,a,b,c,d,x;
ll tot[2]; //统计奇偶
int main(){
n=read(),a=read(),b=read(),c=read(),d=read(),x=read();
a%=d,b%=d,c%=d,x%=d; for(int i=1;i<=n;i++)
tot[__builtin_parity(x=((a*x%d)*x%d+b*x%d+c)%d)&1]++;
printf("%lld\n",tot[0]*tot[1]);
return 0;
}
简易的代码胜过复杂的说教。