• bzoj3668 [Noi2014]起床困难综合症——贪心


    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3668

    一开始想着倒序推回去看看这一位能不能达到来着,因为这样好中途退出(以为不这样会T);

    没想到正着的0和1可能出现一样的结果...

    这是WA代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int const maxn=1e5+5;
    int n,m,t[maxn],ans,cnt[60],op[maxn],c;
    char ch[5];
    int cal(int x)
    {
        memset(cnt,0,sizeof cnt);
        int ret=0;
        while(x)cnt[++ret]=x%2,x/=2;
        return ret;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        int mx=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%s%d",&ch,&t[i]);
            if(ch[0]=='A')op[i]=1;//&
            if(ch[0]=='O')op[i]=2;//|
            if(ch[0]=='X')op[i]=3;//^
            mx=max(mx,t[i]);
        }
        int k=cal(mx);
        for(int i=k;i;i--)
        {
    //        if(ans+(1<<(i-1))>m)continue;
            bool flag=0;int nw=1;
            for(int j=n;j;j--)
            {
                cal(t[j]);
                if(op[j]==1&&nw==1&&cnt[i]==0){flag=1;break;}
                if(op[j]==2&&nw==0&&cnt[i]==1){flag=1;break;}
                if(op[j]==3)nw^=cnt[i];
            }
            if(!flag)
            {
                if(nw==0)ans+=(1<<(i-1));
                else if(c+(1<<(i-1))<=m)c+=(1<<(i-1)),ans+=(1<<(i-1));
            }
        }
        printf("%d",ans);
        return 0;
    }

    而且 i 不是从 mx 的最高位开始而是从 m 的最高位开始的...

    也不用中途退出什么的,因为位数没有那么大;

    可以先用0得到一个 ans 作为底线,然后看看能不能通过某些位上放1让答案更大。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int const maxn=1e5+5;
    int n,m,t[maxn],ans,cnt[60],op[maxn],c;
    char ch[5];
    int cal(int x)
    {
        memset(cnt,0,sizeof cnt);
        int ret=0;
        while(x)cnt[++ret]=x%2,x/=2;
        return ret;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        int mx=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%s%d",&ch,&t[i]);
            if(ch[0]=='A')op[i]=1,ans&=t[i];//&
            if(ch[0]=='O')op[i]=2,ans|=t[i];//|
            if(ch[0]=='X')op[i]=3,ans^=t[i];//^
        }//得到输入0后的ans 
        int k=cal(m);k--;
        for(int i=k;i>=0;i--)
        {
            int tmp=(1<<i);
            if(tmp>m||(ans&(1<<i)))continue;
            for(int j=1;j<=n;j++)
            {
                if(op[j]==1)tmp&=t[j];
                if(op[j]==2)tmp|=t[j];
                if(op[j]==3)tmp^=t[j];
            }
            if(tmp&(1<<i))ans|=(1<<i),m-=(1<<i);
        }
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    Java面向对象XMind
    使用idea插件JRebel热部署的坑
    Mysql小技巧(多行数据合并+模糊查询
    JRebel安装使用
    Shiro(三) 权限管理 假数据
    Shiro(二)通过shiro实现登录 连接数据库+集成Springboot
    Shiro(一)通过shiro实现登录
    poi实现Excel输出
    日志,注解切入点
    获取用户信息
  • 原文地址:https://www.cnblogs.com/Zinn/p/9167201.html
Copyright © 2020-2023  润新知