链接:https://www.nowcoder.com/acm/contest/145/C
来源:牛客网
Bit Compression
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
Special Judge, 64bit IO Format: %lld
题目描述
A binary string s of length N = 2n is given. You will perform the following operation n times :
- Choose one of the operators AND (&), OR (|) or XOR (^). Suppose the current string is S = s1s2...sk. Then, for all , replace s2i-1s2i with the result obtained by applying the operator to s2i-1 and s2i. For example, if we apply XOR to {1101} we get {01}.
After n operations, the string will have length 1.
There are 3n ways to choose the n operations in total. How many of these ways will give 1 as the only character of the final string.
输入描述:
The first line of input contains a single integer n (1 ≤ n ≤ 18). The next line of input contains a single binary string s (|s| = 2n). All characters of s are either 0 or 1.
输出描述:
Output a single integer, the answer to the problem.
示例1
输入
2 1001
输出
4
说明
The sequences (XOR, OR), (XOR, AND), (OR, OR), (OR, AND) works.
题意在map那篇博客里已经说过了,这题也可用dfs做,map的做法不好想但是想出来之后代码好实现,dfs思路好想,但是代码不好实现。dfs怎么想?就是第一次可以从三个里面选一个,选完之后又可以从三个操作符里选一个,就样深搜下去。
然后自己YY了一发。
WA的代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=270000;
char s[maxn];
int FangAn;
int n;
int tmp1[maxn],tmp2[maxn],tmp3[maxn];
void dfs(int d[],int ceng,int logal,int k){
int c;
int cnt=0;
int flag=0;
if(ceng==n)
{
if(logal==1)
{
for(int i=1;i<=k/2;i++)
{
d[++cnt]=(d[2*i-1]^d[2*i]);
}
}
else if(logal==2)
{
for(int i=1;i<=k/2;i++)
{
d[++cnt]=(d[2*i-1] | d[2*i]);
}
}
else
{
for(int i=1;i<=k/2;i++)
{
d[++cnt]=(d[2*i-1] & d[2*i]);
}
}
if(d[1]==1)
{
//cout<<"FangAn"<<FangAn<<endl;
FangAn++;
}
//cout<<d[1]<<" %%%% "<<endl;
return ;
}
if(logal==1){
for(int i=1;i<=k/2;i++){
d[++cnt]=(d[2*i-1]^d[2*i]);
cout<<cnt<<" "<<d[cnt]<<" $$ "<<endl;
if(d[cnt]==1)
flag=1;
}
c=ceng;
c+=1;
if(flag==0)
{return;}
dfs(d,c,1,cnt);
dfs(d,c,2,cnt);
dfs(d,c,3,cnt);
}
else if(logal==2){
for(int i=1;i<=k/2;i++){
d[++cnt]=(d[2*i-1] | d[2*i]);
cout<<cnt<<" "<<d[cnt]<<" YY "<<endl;
if(d[cnt]==1)
flag=1;
}
//ceng+=1;
c=ceng;
c+=1;cout<<c<<" "<<flag<<" TT "<<endl;
if(flag==0)
return;
dfs(d,c,1,cnt);cout<<FangAn<<" QQ "<<endl;
dfs(d,c,2,cnt);cout<<FangAn<<" WW "<<endl;
dfs(d,c,3,cnt);cout<<FangAn<<" RR "<<endl;
}
else{
for(int i=1;i<=k/2;i++)
{
cout<<d[2*i-1]<<" "<<d[2*i]<<" ||| "<<endl;
d[++cnt]=(d[2*i-1] & d[2*i]);
cout<<cnt<<" "<<d[cnt]<<" +++ "<<endl;
if(d[cnt]==1)
flag=1;
}
c=ceng;
c+=1;
if(flag==0)
{return;}
dfs(d,c,1,cnt);
dfs(d,c,2,cnt);
dfs(d,c,3,cnt);
}
}
int main()
{
FangAn=0;
scanf("%d",&n);
int length=pow(2,n);
scanf("%s",s);
for(int i=0;i<length;i++){
if(s[i]=='0') tmp1[i+1]=0,tmp2[i+1]=0,tmp3[i+1]=0;
else tmp1[i+1]=1,tmp2[i+1]=1,tmp3[i+1]=1;
}
dfs(tmp1,1,1,length);cout<<FangAn<<" ### "<<endl;
dfs(tmp2,1,2,length);cout<<FangAn<<" ^^^ "<<endl;
//dfs(tmp3,1,3,length);cout<<FangAn<<" *** "<<endl;
cout<<FangAn<<endl;
}
一开始就用了一个tmp,发现运行完主函数里的dfs(tmp,1,1,length),再输出tmp一看tmp变了,但是tmp不能变,感觉tmp不会变啊,只是让tmp去运行dfs,不知道怎么弄得,好吧既然变了我就用三个tmp来弄,这个小bug改完了。发现dfs里三个dfs摞在一起的那三个语句,执行完第一个d数组就变了,但是d数组也不能变。所以虽然是那样想,但是代码不是按想的思路走的。
所以想办法不要让d数组改变。
AC代码
#include<bits/stdc++.h>
using namespace std;
char dp[20][300000];
long long ans;
char op(int k,char a,char b){
int aa=a-'0';
int bb=b-'0';
if(k==0) return (aa&bb)+'0';
if(k==1) return (aa|bb)+'0';
if(k==2) return (aa^bb)+'0';
return '0';
}
void dfs(int cur){
if(cur==0){
if(dp[cur][0]=='1'){
ans++;
}
return;
}
for(int k=0;k<3;k++){
int cnt=0;
for(int i=0;i<(1<<cur);i+=2){
char ch=op(k,dp[cur][i],dp[cur][i+1]);
if(ch=='1') cnt++;
dp[cur-1][i/2]=ch;
}
if(cnt==0) continue;
dfs(cur-1);
}
}
int main(){
int n;
scanf("%d",&n);
scanf("%s",dp[n]);
ans=0;
dfs(n);
printf("%lld\n",ans);
}