链接:https://www.nowcoder.com/acm/contest/145/C
来源:牛客网
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.
- Choose one of the operators AND (&), OR (|) or XOR (^). Suppose the current string is S = s1s2...sk. Then, for all
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| = 2
n
). All characters of s are either 0 or 1.
输出描述:
Output a single integer, the answer to the problem.
示例1
说明
The sequences (XOR, OR), (XOR, AND), (OR, OR), (OR, AND) works.
题意:给你2^n个数,每次可以将前2^(n-1)个数和后2^(n-1)个数进行二进制与、或、异或操作中的一种,问有多少种不同的操作顺序使得最后的结果为一个一?
分析:考虑直接暴力的时间复杂度是3^18,这个数与题目给出的时间限制已经很接近,所以我们只需要在直接暴力的基础上做一点点优化就可以了
考虑如果最后要得到一个一,则数列中一定要还存在一,否则无论与、或、异或操作都无法再得到一
所以我们只需要在暴力的时候判断下剩下的数中是否还有一,没有一就没必要继续操作
AC代码:
#include <map> #include <set> #include <stack> #include <cmath> #include <queue> #include <cstdio> #include <vector> #include <string> #include <bitset> #include <cstring> #include <iomanip> #include <iostream> #include <algorithm> #define ls (r<<1) #define rs (r<<1|1) #define debug(a) cout << #a << " " << a << endl using namespace std; typedef long long ll; const ll maxn = 1e6 + 10; const double eps = 1e-8; const ll mod = 1e9 + 7; const ll inf = 1e9; const double pi = acos(-1.0); string s; ll t[maxn*2]; //开始将数字存在1<<n后,每次数字合并后产生的1<<(n-1)往前面放,方便合并运算 ll res = 0; void dfs( ll n ) { if( n == -1 ) { if( t[2] == 1 ) { //只剩一个一 res ++; } return ; } ll k = 1<<n; for( ll j = 0; j <= 2; j ++ ) { ll cnt = 0; for( ll i = 1; i <= k; i ++ ) { ll tmp = i+k; if( j == 0 ) { t[tmp] = t[tmp*2-1]^t[tmp*2]; } else if( j == 1 ) { t[tmp] = t[tmp*2-1]|t[tmp*2]; } else { t[tmp] = t[tmp*2-1]&t[tmp*2]; } if( t[tmp] == 0 ) { cnt ++; } } if( cnt == k ) { //如果都是零就不可能再出现一 continue; } dfs(n-1); } } int main() { ll n; cin >> n; cin >> s; ll k = 1<<n; for( ll i = 1; i <= k; i ++ ) { t[i+k] = s[i-1] - '0'; } dfs(n-1); cout << res << endl; return 0; }