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’。取代后有
种可能
和
,其中
、
,所以最大的可能值是
。
样例的第二组询问算式为:‘1?1?1’。取代后有
种可能
,
,
和
,其中
、
,所以最大的可能值是
。
样例的第三组询问算式为:
。并不包含问号,只有唯一的运算结果
。
样例的第四组询问算式为:
。并不包含问号,只有唯一的运算结果
。
题意
给定一个式子,式子由多个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;
}