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;
}

 

posted @ 2016-09-29 18:48  Fighting_Heart  阅读(222)  评论(0编辑  收藏  举报