• 【BZOJ5285】[HNOI2018]寻宝游戏(神仙题)


    【BZOJ5285】[HNOI2018]寻宝游戏(神仙题)

    题面

    BZOJ
    洛谷

    题解

    既然是二进制按位的运算,显然按位考虑。
    发现这样一个关系,如果是(or)的话,只要(or 1),那么无论前面是啥,操作完之后都是(1);同理(and 0)也是一样,无论前面是什么,操作完都是(0)
    换个角度来看,如果(or 0),无论前面是什么,操作完之后都不改变,(and 1)同理。
    那么把(or)写成(0)(and)写成(1)
    那么,如果当前操作数前面的运算符和某一位上相同,那么就等价于没有进行操作,否则直接知道了运算结果。
    假如只有一个二进制位的话,那么就是一个长度为(n)(01)(x),和一个长度为(n)的操作串(opt)。设最后一位为最高位。
    如果最终的结果是(1),那么意味着(x>opt),否则最终结果为(0)。可以手玩验证。
    大致的证明的话,如果最后结果是(1),意味着最后一个(or 1)的操作一定要在最后一个(and 0)的操作之后。再把(or)(and)换成(01)表示就可以得到这个结论。
    这样一来就变成了比大小的问题了。我们可以算出(xle opt<y),那么答案就是(y-x)
    然后一个细节问题,首先提前把每一位按照(x)排好序,用基数排序即可。这样子可以直接(for)结果为(0)的最大值和结果为(1)最小值。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    #define MAX 5050
    #define MOD 1000000007
    char ch[MAX];
    int g[1010][MAX],bin[1010],n,m,q;
    int c[2],a[MAX],b[MAX],s[MAX],t[MAX];
    int main()
    {
    	scanf("%d%d%d",&n,&m,&q);
    	bin[0]=1;for(int i=1;i<=n;++i)bin[i]=2*bin[i-1]%MOD;
    	for(int i=1;i<=m;++i)a[i]=i;
    	for(int i=1;i<=n;++i)
    	{
    		scanf("%s",ch+1);c[0]=0;c[1]=m;
    		for(int j=1;j<=m;++j)(ch[j]-48)?s[j]=(s[j]+bin[i-1])%MOD:++c[0];
    		for(int j=m;j;--j)b[c[ch[a[j]]-48]--]=a[j];
    		for(int j=1;j<=m;++j)a[j]=b[j];
    	}
    	for(int i=1;i<=m;++i)t[i]=s[a[i]];t[m+1]=bin[n];
    	while(q--)
    	{
    		scanf("%s",ch+1);int mx=m+1,mn=0;
    		for(int i=m;i;--i)if(ch[a[i]]-48==0){mn=i;break;}
    		for(int i=1;i<=m;++i)if(ch[a[i]]-48){mx=i;break;}
    		printf("%d
    ",mn>mx?0:(t[mx]-t[mn]+MOD)%MOD);
    	}
    	return 0;
    }
    
  • 相关阅读:
    spring 定时任务
    maven出现(请使用source 5 或者更高版本以启用XX)问题解决
    eclipse启动tomcat出现内存溢出错误 java.lang.OutOfMemoryError: PermGen space
    开源 免费 java CMS FreeCMS标签 linkClass .
    相对你们说的一些话
    就业形势如此的严峻,你为何不努力?
    使用C#操作XML文件
    优秀学生专栏——董超
    想对你们每个人说的话
    班级第一次问卷调查
  • 原文地址:https://www.cnblogs.com/cjyyb/p/10230774.html
Copyright © 2020-2023  润新知