Bit Compression 两种解决方案 O(∩_∩)O哈哈~-程序员宅基地

技术标签: 位运算  

题目链接

方法一(暴力):这题很容易看出来是个典型的dfs题,只要注意剪枝(把结果一定为0的情况进行剪枝)就能过,下面是代码:

#include<cstdio>
using namespace std;
bool a[1 << 18];
int dfs(int n, bool* s) {
    
	if (n == 1) return 1;
	n >>= 1; bool b[n]; int ans = 0, h1 = 0, h2 = 0, h3 = 0;
	for(int i=0;i<n;++i)h1+=b[i]=(s[i<<1]&s[i<<1|1]); if(h1)ans+=dfs(n,b);
	for(int i=0;i<n;++i)h2+=b[i]=(s[i<<1]|s[i<<1|1]); if(h2)ans+=dfs(n,b);
	for(int i=0;i<n;++i)h3+=b[i]=(s[i<<1]^s[i<<1|1]); if(h3)ans+=dfs(n,b);
	return ans;
}
int main() {
    
	int n; scanf("%d%*c", &n);
	for(int i=0;i<(1<<n);++i) a[i]=getchar()-'0';
	printf("%d\n", dfs(1 << n, a));
	return 0;
}

方法二(非暴力): 对dfs进行记忆优化,用数位dp求得二进制颠倒排序,高精度压位防止数据溢出等。(速度要比暴力法快很多)代码如下:

#include<cstdio>

using namespace std;

const int  N  = 1 << 18;

int a[N], pos[N], b[N];// a存储输入串,pos存储序列,b存储记忆化 
unsigned c[N], d[N];// c存储高精度压位,d存储过程临时数据 

void Bitsort(int n) {
     // 数位dp 
	for(int i = 0; i <= (1 << n); ++i) {
    
		pos[i] = pos[i>>1]>>1|(i&1)<<(n-1);
	} 
}

int pre(int n, int last) {
     // 记忆优化 
	if (n == 1) return last&1;
	n >>= 1;
	int x = last, y = last >> n;
	return pre(n,x&y)+pre(n,x|y)+pre(n,x^y);
}

int dfs(int n, unsigned* last, unsigned* next) {
     // dfs
	if (n == 1 ) return last[0] & 1;
	if (n == 16) return b[last[0] & 0xffff];
	int ans = 0;
	if (n > 32){
    
		int temp = n / 64;
		for(int i = 0; i < temp; ++i) next[i] = last[i] & last[i+temp];
		ans += dfs(n / 2, next, next + temp);
		for(int i = 0; i < temp; ++i) next[i] = last[i] | last[i+temp];
		ans += dfs(n / 2, next, next + temp);
		for(int i = 0; i < temp; ++i) next[i] = last[i] ^ last[i+temp];
		ans += dfs(n / 2, next, next + temp); 
	}
	else {
    
		int x = last[0];
		int y = last[0] >> n / 2;
		next[0] = x & y;
		ans += dfs(n / 2, next, next + 1);
		next[0] = x | y;
		ans += dfs(n / 2, next, next + 1);
		next[0] = x ^ y;
		ans += dfs(n / 2, next, next + 1);
	}
	return ans;
} 

int main() {
    
	int n;
	scanf("%d%*c", &n);
	/******************************** 
	二进制颠倒排序 
	以二进制颠倒序列输入 
 	高精度压位(以二进制32位 -> 十进制) 
 	在进行深搜前对n=4,进行记忆化 
	***********************************/
	Bitsort(n);
	for(int i=0;i<1<<n;++i) a[pos[i]]=getchar()-'0';
	for(int i=0;i<1<<n;++i) c[i/32]|=(unsigned)a[i]<<(i%32);
	for(int i=0;i<1<<16;++i) b[i]=pre(16,i);
	printf("%d\n", dfs(1 << n, c, d)); 
	return 0; 
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Long_hen/article/details/105330024

智能推荐

为什么int常量可以直接赋给byte,short,而double常量不能直接赋给float?_c++ double类型不可以赋值给float类型-程序员宅基地

将一个整型的常量(字面值为int)赋给一个byte或者short类型的变量,只要不超过byte或short取值范围,就可以通过编译byte a = 1;//编译通过short b = 1;//编译通过将一个浮点型的常量(字面值的double)赋给一个float类型的变量,即使不超过float的取值范围,也会出现编译错误float c = 1.2;//编译报错因为1.2默认为double类型,而double的数据类型范围大于float数据类型的范围,所以编译出现错误!请问为什么Java中会有这种双_c++ double类型不可以赋值给float类型

linux常用命令详解-程序员宅基地

Linux必学的60个命令Linux提供了大量的命令,利用它可以有效地完成大量的工 作,如磁盘操作、文件存Linux提供了大量的命令,利用它可以有效地完成大量的工作,如磁盘操作、文件存取、目录操作、进程管理、文件权限设定等。所以,在Linux系统上工作离不开使用系统提供的命令。要想真正理解Linux系统,就必须从Linux命令学起,通过基础的命令

PAT B1005. 继续(3n+1)猜想_(pat)继续(3n+1)猜想-程序员宅基地

卡拉兹(Callatz)猜想已经在1001中给出了描述。在这个题目里,情况稍微有些复杂。当我们验证卡拉兹猜想的时候,为了避免重复计算,可以记录下递推过程中遇到的每一个数。例如对n=3进行验证的时候,我们需要计算3、5、8、4、2、1,则当我们对n=5、8、4、2进行验证的时候,就可以直接判定卡拉兹猜想的真伪,而不需要重复计算,因为这4个数已经在验证3的时候遇到过了,我们称5、8、4、2是被_(pat)继续(3n+1)猜想

神雕侠侣2服务器维护,神雕侠侣2手游11月28日停服维护了什么-程序员宅基地

神雕侠侣2手游11月28日停服维护了什么,很多网友都遇到了这样的问题。这个问题该如何解决呢?下面小编就带来神雕侠侣2手游11月28日更新内容汇总,希望可以帮到你!亲爱的少侠为了给您带来更好的游戏体验,《神雕侠侣2》手游将于11月28日9:00-10:00进行例行停服维护,届时将无法登入游戏。若提前完成维护,我们将提前开服。请各位少侠提前做好准备,以免造成损失。维护结束后将统一奉上补偿,感谢您的支持...

mybatis:select语句_"<select id=\"selectdemandcirculationdetailbyid\" -程序员宅基地

一.常用属性举例:<select id="selectPerson" parameterType="int" resultType="hashmap"> SELECT * FROOM PRESON WHERE ID = #{id}</select>属性配置实例<select id="selectPerson" parame..._"

随便推点

charles抓取https中出现unknow的解决方法-程序员宅基地

环境:Mac、iOS首先要配置抓取http的方法。1.第一是下载 charles, 这里选择的是破解版v 4.2 ,如下地址可获得最新软件http://charles.iiilab.com/http的配置还是很简单,关键是https的,大部分我们是用抓包就是想用这个功能。打开Charles, 点击Help-&gt;SSL Proxying-&gt;Install Charl...

C# DataTable 某一列求和_dt 求和-程序员宅基地

列为数字类型double total= Convert.ToDouble(datatable.Compute(“SUM(需要求和的参数)”, “”));2.列为string 类型 先转为数字类型 再求和double total= dt.AsEnumerable().Select(d => Convert.ToDouble(d.Field(“amount”))).Sum();..._dt 求和

GAN相关引用/被引用的文章_generating adversarial malware examples for black--程序员宅基地

DDAlex 2019-03-05 14:37 原文链接:https://msd.misuland.com/pd/2884250137616454120原论文:Generating Adversarial Malware Examples for Black-Box Attacks Based on GAN引用论文:2001 Data Mining Methods ..._generating adversarial malware examples for black-box attacks based on gan引

2017-5-11 工作第二天,开始记录_御坂镜的博客-程序员宅基地

大家好,我是山西农业大学软件学院来的码农。2013年9月到2016年6月在山西太谷上大学,2016年9月到帝都实训,2017年4月开始找工作。 在校期间我经历说丰富也算丰富,创业、社团、贴吧、学生会、兼职,什么都干了,没挂科,走自己的路,没事写写代码。但是遗憾也多,撇不到妹子,玩的不尽兴,学的有几下子,但是离大神还远的很。技能树点的有些歪,初中就点了数字媒体,大三突然走了java开发。还是审

VLAN详解-程序员宅基地

转自https://blog.51cto.com/6930123/2115373一、为什么需要VLAN1.1、什么是VLAN?VLAN(Virtual LAN),翻译成中文是“虚拟局域网”。LAN可以是由少数几台家用计算机构成的网络,也可以是数以百计的计算机构成的企业网络。VLAN所指的LAN特指使用路由器分割的网络——也就是广播域。在此让我们先复习一下广播域的概念。广播域...

推荐文章

热门文章

相关标签