2019 年百度之星·程序设计大赛 - 初赛二 1003 度度熊与运算式 1 HDU 6676

2019 年百度之星·程序设计大赛 - 初赛二 1003 度度熊与运算式 1 HDU 6676

Problem Description

某天度熊发现了一个由 n+1 个数字 1 组成的运算式如下:
1 op1 1 op2 1 … 1 opn 1
其中 opi 可能是 ⊕ (按位异或运算) 或是 ? (问号)。
例如当 n=5 时,式子可能长成这样:1⊕1 ? 1⊕1 ? 1 ? 1
现在,度熊想把所有的 ‘?’ 取代为 + 或 ⊕。
(贴心提示: 加法运算的优先级比按位异或运算还高)
请问取代完后此运算式可能的最大运算结果为何?

Input

有多组询问,第一行包含一个正整数 T 代表有几组询问,接着每组测试数据占一行,包含一个长度为 n 的字符串,仅由 '^ '和 ‘?’ 组成,第 i 个字符若是 ‘^’ 就代表 opi=⊕,否则 opi 就是问号。(n 的值不会在数据中出现,请由字符串长度来判断。)

  • 1≤n≤221−2
  • 所有询问的 n 的总和不超过 2×107

Output

对于每一个询问输出一行包含一个整数代表答案,也就是该算式的问号被取代后可能的最大运算结果。

Sample Input

4
?
??
^^
^^^
Sample Output
2
3
1
0
Note
样例的第一组询问算式为:‘1?1’。取代后有 2 2 种可能 1 + 1 1+1 1 1 1\oplus1 ,其中 1 + 1 = 2 1+1=2 1 1 = 0 1\oplus1=0 ,所以最大的可能值是 2 2
样例的第二组询问算式为:‘1?1?1’。取代后有 4 4 种可能 1 + 1 + 1 1+1+1 , 1 + 1 1 1+1\oplus1 , 1 1 + 1 1\oplus1+1 1 1 1 1\oplus1\oplus1 ,其中 1 + 1 + 1 = 1 + 1 1 = 1 1 + 1 = 3 1+1+1=1+1\oplus1=1\oplus1+1=3 1 1 1 = 1 1\oplus1\oplus1=1 ,所以最大的可能值是 3 3
样例的第三组询问算式为: 1 1 1 1\oplus1\oplus1 。并不包含问号,只有唯一的运算结果 1 1
样例的第四组询问算式为: 1 1 1 1 1\oplus1\oplus1\oplus1 。并不包含问号,只有唯一的运算结果 0 0


题意

给定一个式子,式子由多个1异或或者相加构成,现在知道部分位置为异或,其他地方未知,问怎么选择未知的符号(加或者异或),使得这个式子的值最大。

思路

首先将所有的未知符号按+处理,然后我们按位考虑这些数,我们尽量保证每一位二进制位的数值都为1,这样可以保证式子的值最大,然后我们把这一串连续问号中的多余的1放在这一串连着的问号末尾,按照异或处理。然后记录最后需要异或上的1的个数,然后判断个数的奇偶性确定二进制的最低位。

坑点

代码第44行到第56行。咋都想不到。。。


代码

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)

const int N=2e6+5;

char str[N];
int num[N];
int counter=0;
int vis[30];

inline void init()
{
    memset(vis,0,sizeof(vis));
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        init();
        scanf("%s",str);
        int len=strlen(str);
        int cnt=0;
        counter=0;
        rep(i,0,len)
        {
            if(str[i]=='^'||str[i]=='\0')
            {
                num[counter++]=cnt+1;
                cnt=0;
            }
            else
                cnt++;
        }
        sort(num,num+counter);
        per(i,counter-1,0)
        {
            cnt=0;
            int flag=0;
            per(j,29,1)
            {
                if(num[i]>=(1<<j)&&!vis[j])
                {
                    vis[j]=1;
                    num[i]-=(1<<j);
                }
            }
        }
        ll ans=0;
        per(i,29,0)
        {
            ans*=2;
            ans+=vis[i];
        }
        if((len+1-ans)%2==1)
        {
            if(ans%2==0)
                ans++;
            else
                ans--;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

发布了42 篇原创文章 · 获赞 6 · 访问量 4024

猜你喜欢

转载自blog.csdn.net/qq_43383246/article/details/99768097