发现每个位置是等价的,这样如果 n n n为偶数那么答案是 0 0 0,否则为所有方案数中 a 1 a_1 a1的异或和
发现题目设计的非常巧妙,加上 ( OR i = 1 n a i ) ⊆ y (\text{OR}_{i=1}^n a_i)\subseteq y (ORi=1nai)⊆y 的限制过后,变量的取值就有了范围,我们可以利用这一条件对式子进行化简
考虑钦定 a 1 a_1 a1的第 k k k位为 1 1 1,然后计算方案数为: ∑ ∑ a i = x − 2 k [ a 1 ⊆ y − 2 k ] [ a 2 ⊆ y ] . . . [ a n ⊆ y ] = ∑ ∑ a i = x − 2 k ( y − 2 k a 1 ) ( y a 2 ) . . . ( y a n ) = ( n y − 2 k x − 2 k ) = [ ( x − 2 k ) ⊆ ( n y − 2 k ) ] \begin{aligned}&\sum_{\sum a_i=x-2^k}[a_1\subseteq y-2^k][a_2\subseteq y]...[a_n\subseteq y] \\ &= \sum_{\sum a_i=x-2^k}\binom{y-2^k}{a_1}\binom{y}{a_2}...\binom{y}{a_n} \\&= \binom{ny-2^k}{x-2^k} \\&=[(x-2^k)\subseteq (ny-2^k)]\end{aligned} ∑ai=x−2k∑[a1⊆y−2k][a2⊆y]...[an⊆y]=∑ai=x−2k∑(a1y−2k)(a2y)...(any)=(x−2kny−2k)=[(x−2k)⊆(ny−2k)]
可以 O ( 1 ) O(1) O(1)计算。最后枚举 y y y的子集容斥计算即可。
复杂度 O ( y log y ) O(y\log y) O(ylogy)。
代码真的很短
#include
#define fi first
#define se second
#define pb push_back
#define db double
#define ll long long
#define ull unsigned long long
using namespace std;
ll n,x,y,res;
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n>>x>>y;
if(n%2==0){
cout<<0;
return 0;
}
for(ll i=y;i;i=(i-1)&y){
for(int j=0;j<20;j++){
if(i>>j&1){
ll a=x-(1<<j),b=n*i-(1<<j);
if(a>=0&&b>=0&&(a&b)==a){
res^=(1<<j);
}
}
}
}cout<<res;
}