zoukankan      html  css  js  c++  java
  • [HNOI2012]与非

    题目描述

    NAND(与非)是一种二元逻辑运算,其运算结果为真当且仅当两个输入的布尔值不全为真。NAND运算的真值表如下(1表示真,0表示假):

    两个非负整数的NAND是指将它们表示成二进制数,再在对应的二进制位进行NAND运算。由于两个二进制数的长度可能不等,因此一般约定一个最高位K,使得两个数的二进制表示都不 超过K位,不足K位的在高位补零。给定N个非负整数A1,A2......AN和约定位数K,利用NAND运算与括号,每个数可以使用任意次,请你求出范围[L,R]内可以被计算出的数有多少个。

    输入输出格式

    输入格式:

    输入文件第一行是用空格隔开的四个正整数N,K,L和R,接下来的一行是N个非负整数A1,A2......AN,其含义如上所述。 100%的数据满足K<=60且N<=1000,0<=Ai<=2^k-1,0<=L<=R<=10^18

    输出格式:

    仅包含一个整数,表示[L,R]内可以被计算出的数的个数

    输入输出样例

    输入样例#1: 复制
    3  3 1 4
    3  4 5
    输出样例#1: 复制
    4

    说明

    样例1中,(3 NAND 4) NADN (3 NAND 5) = 1,5 NAND 5 = 2,3和4直接可得。

    可以表示出其他所有的位运算

    $not A=A nand A$

    $A and B=not (A nand B)$

    $A or B=(not A) nand (not B)$

    $A xor B=(A and not B) or (not A and B)$

    所以相当于是这$n$ 个数之间可以做任何位运算。

    如果这$n$ 个数中每个数的第$i$ 位和第$j$ 位都相同,那么这$n$ 个数无论怎么运算,最后得到的答案中第$i$ 位和第$j$ 位一定相同

    然后就是数位dp

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 using namespace std;
     7 typedef long long lol;
     8 lol tmp[81],c[81],cnt[81],Q[81][81];
     9 lol a[2001],k,n,L,R;
    10 lol dfs(lol s,lol x,lol flag)
    11 {lol i,j;
    12   if (x<0) return 1;
    13   if (!flag)
    14   {
    15     memcpy(tmp,c,sizeof(c));
    16     lol tot=0;
    17     for (i=x;i>=0;i--)
    18       if (tmp[i]==-1)
    19       {
    20         tot++;
    21         for (j=0;j<=cnt[i];j++)
    22           {
    23             tmp[Q[i][j]]=1;
    24           }
    25       }
    26     return 1ll<<tot;
    27   }
    28   lol ed=((s>>x)&1);
    29   lol sum=0;
    30   if (c[x]==-1)
    31     {
    32       for (i=0;i<=ed;i++)
    33         {
    34           for (j=0;j<=cnt[x];j++)
    35             {
    36               c[Q[x][j]]=i;
    37             }
    38           sum+=dfs(s,x-1,flag&(i==ed));
    39         }
    40       for (j=0;j<=cnt[x];j++)
    41         {
    42       c[Q[x][j]]=-1;
    43         }
    44       return sum;
    45     }
    46   else
    47     {
    48       if (flag&&c[x]&&ed==0) return 0;
    49       return dfs(s,x-1,flag&(c[x]==ed));
    50     }
    51 }
    52 lol solve(lol s)
    53 {
    54   memset(c,-1,sizeof(c));
    55   if (s<0) return 0;
    56   return dfs(s,k-1,(s>>k)?0:1);
    57 }
    58 int main()
    59 {lol i,j,l,flag;
    60   cin>>n>>k>>L>>R;
    61   for (i=1;i<=n;i++)
    62     scanf("%lld",&a[i]);
    63   for (i=k-1;i>=1;i--)
    64     {
    65       for (j=i-1;j>=0;j--)
    66         {
    67           flag=0;
    68           for (l=1;l<=n;l++)
    69             if (((a[l]>>i)&1)^((a[l]>>j)&1))
    70               {
    71             flag=1;break;
    72               }
    73           if (flag==0)
    74             Q[i][++cnt[i]]=j;
    75         }
    76       Q[i][0]=i;
    77     }
    78   printf("%lld
    ",solve(R)-solve(L-1));
    79 }
  • 相关阅读:
    39门课程。加油!学长只能帮你到这里了!
    联邦企业架构之CIO委员会的企业架构实施指南(上)
    RTEMS 进程切换分析
    styleCop使用介绍和Fxcop使用参考
    获得Web目录URL
    HelloWorld demo
    第一个C语言程序
    文件分布式存储方案
    Linux常用指令别名、输入/输出重定向、管道、命令连接符、命令替换符
    JavaEE项目问题总结
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8541550.html
Copyright © 2011-2022 走看看