zoukankan      html  css  js  c++  java
  • 【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;
    }
    
  • 相关阅读:
    Python什么是二次开发的意义?python在.net项目采用
    斐波那契数
    Java 兑换ObjectC代码
    第18本:《整理的艺术》
    第16本:《视觉繁美:信息可视化方法与案例解析》
    第14本:《李鸿章传》
    第10本:《设计心理学》
    第17本:《代码的未来》
    第15本:《视不可当----信息图与可视化传播》
    第13本:《富爸爸,穷爸爸》
  • 原文地址:https://www.cnblogs.com/cjyyb/p/10230774.html
Copyright © 2011-2022 走看看