牛客网暑期ACM多校训练营(第七场)- C - Bit Compression
题意:
一个长度为2^n的二进制数,每次对这个数进行&、^、|三种操作中的一种,每次操作将两个相邻的数进行该操作得到新的二进制数,然后继续向下,求最后剩下一个1有多少种方法。
整个效率为O(3^n)在最后几步记忆化一下就能过了。
太多步的话要存的状态太多空间会炸,所以适当就好。
#include <iostream>
#include <stdio.h>
#include <map>
using namespace std;
typedef long long int LL;
map<LL, LL>mp;
LL dfs(int *s,int sz){
LL ss = 0;
if(sz <= 16) {
for(int i=0;i<sz;i++) ss = ss * 3 + s[i] + 1;
if(mp.count(ss)) return mp[ss];
}
LL ans = 0;
int *tem = new int[sz/2 + 10];
int len = sz / 2;
for(int i=0;i<len;i++) tem[i] = s[i*2] & s[i*2+1];
ans += dfs(tem, len);
for(int i=0;i<len;i++) tem[i] = s[i*2] ^ s[i*2+1];
ans += dfs(tem, len);
for(int i=0;i<len;i++) tem[i] = s[i*2] | s[i*2+1];
ans += dfs(tem, len);
delete [] tem;
return sz <=16 ? mp[ss] = ans : ans;
}
int main()
{
mp[2] = 1; mp[1] = 0;
int n; scanf("%d", &n); getchar();
int *a = new int [1<<n+10];
for(int i=(1<<n)-1;i>=0;i--) a[i] = getchar() - '0';
printf("%lld\n", dfs(a, 1<<n));
return 0;
}