CodeForces 635C XOR Equation
位运算。
又涨姿势了:$a + b = (aXORb) + 2*(aANDb)$,$ (aXORb)$是不进位的部分,$2*(aANDb)$为进位之后的部分,相加就是$a + b$。
知道了这个转换,这题就很容易了。设$n=a+b$,$m=(aXORb)$,$x=(aAND b)$;$n$、$m$和$x$都是已知的。
题目要求统计有多少$(a,b)$满足:
$\left\{ {\begin{array}{*{20}{c}}
{a + b = n}\\
{aXORb = m}
\end{array}} \right.$
等价于统计有多少$(a,b)$满足:
$\left\{ {\begin{array}{*{20}{c}}
{aAND b = x}\\
{aXORb = m}
\end{array}} \right.$
因此,可以按位统计,然后乘法原理乘一下就得到了答案。如果$n=m$,答案还需要减$2$,因为多统计了$0$ $n$和$n$ $0$。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<bitset> #include<iostream> using namespace std; typedef long long LL; const double pi=acos(-1.0),eps=1e-6; void File() { freopen("D:\\in.txt","r",stdin); freopen("D:\\out.txt","w",stdout); } template <class T> inline void read(T &x) { char c=getchar(); x=0; while(!isdigit(c)) c=getchar(); while(isdigit(c)) {x=x*10+c-'0'; c=getchar();} } LL n,m,ans=1; LL b[50],c[50]; int main() { cin>>n>>m; if(m>n) { printf("0\n"); return 0; } if((n-m)%2!=0) { printf("0\n"); return 0; } b[0]=1; for(int i=1;i<=40;i++) b[i]=2*b[i-1]; LL x=(n-m)/2; for(int i=0;i<=40;i++) { for(int s1=0;s1<=1;s1++) { for(int s2=0;s2<=1;s2++) { LL f1,f2; if((m&b[i])) f1=1; else f1=0; if((x&b[i])) f2=1; else f2=0; if((s1^s2)!=f1) continue; if((s1&s2)!=f2) continue; c[i]++; } } } for(int i=0;i<=40;i++) ans=ans*c[i]; if(n==m) ans=ans-2; cout<<ans<<endl; return 0; }