2018 牛客多校第七场 C Bit Compression (DFS+剪枝)

https://www.nowcoder.com/acm/contest/145/C

题意:给你一个n,再给你一个长度为2的n次方的01串。每次字符串可以选择三种操作:& | ^。选择之后,相邻的字符按这个操作合并:比如 1101 选择^  则   1^1=0  0^1=1; 然后字符串就变成了01。继续操作直到剩余一个字符。问你最后只剩一个1的方法总数有多少种。

思路:

直接爆搜会TLE,注意剪枝,如果全为0的,这三种操作怎么操作都不可能是1,所以直接停止。

保存每次操作的答案可以模仿线段树一样,最底下的一层是原串,然后一层一层网上递归,最后判断根节点是否为1,这样就不会破坏原来的字符串了。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e6+10;
char c[maxn];
int t[maxn*4];
int ans;
void dfs(int n)
{
    if(n==-1)
    {
        if(t[1]==1)
        {
            ans++;
        }
        return;
    }
    int k=1<<n;
    for(int i=0;i<3;i++)
    {
        int zz=0;
        for(int j=0;j<k;j++)
        {
            int te=j+k;
            if(i==0)
            {
                t[te]=t[te*2]|t[te*2+1];
            }
            if(i==1)
            {
                t[te]=t[te*2]^t[te*2+1];
            }
            if(i==2)
            {
                t[te]=t[te*2]&t[te*2+1];
            }
            if(!t[te])zz++;
        }
        if(zz==k)continue;
        dfs(n-1);
    }
}
int main()
{
    int n;
    scanf("%d",&n);
    scanf("%s",c);
    int k=1<<n;
    for(int i=0;i<k;i++)
    {
        t[i+k]=c[i]-'0';
    }
    ans=0;
    dfs(n-1);
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/imzxww/article/details/81564210