容易发现x nand x=not x。并且使用这个性质有x and y=not(x nand y)=(x nand y)nand(x nand y)。也就是说nand运算可以作为not和and运算使用。并且显然not和and运算可以表示nand运算,那么两者等价。事实上这就可以表示所有位运算了。
那么考虑位运算有什么事干不了。注意到如果每个数的第i位都和第j位相同, 那么无论怎么操作这两位都是相同的。大胆猜想这也是充分的,即除了这件事其他都能干。
这样位就被分成了很多类,每一类的取值要求相同。类似数位dp搞一发考虑第一个未达限制的是哪一位就行了。
各种细节,调到吐血,拿过7种分数,连过了都不知道是不是数据水了,没救。
#include#include #include #include #include #include using namespace std;#define N 1010#define K 60#define ll long longll read(){ ll x=0,f=1;char c=getchar(); while (c<'0'||c>'9') { if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f;}int n,k,d[K][K],fa[K];bool flag[K];ll l,r,num[K];int find(int x){ return fa[x]==x?x:fa[x]=find(fa[x]);}ll calc(ll n){ ll s=0,m=0,cnt=0; for (int i=0;i n) break; } } for (int i=0;i 0)!=((n&(1ll< 0)) return s; return s+1;}int main(){#ifndef ONLINE_JUDGE freopen("bzoj2728.in","r",stdin); freopen("bzoj2728.out","w",stdout); const char LL[]="%I64d\n";#else const char LL[]="%lld\n";#endif n=read(),k=read(),l=read(),r=read(); if (l>=(1ll< 0)!=((x&(1ll< 0)) d[p][q]=0; } for (int i=0;i