ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

「JOI 2018 Final」毒蛇越狱

2021-11-16 19:31:49  阅读:209  来源: 互联网

标签:复杂度 研究所 毒蛇 2018 JOI 逃跑 Final cnt2


「JOI 2018 Final」毒蛇越狱

题面:

JOI 研究所有 条毒蛇,这些毒蛇编号为 \(0,1,\dots,2^L-1\) 。每条毒蛇从头到尾被分成 \(L\) 段,每段的颜色为蓝、红中的一种。对于毒蛇 \(i\),令 \(i=\sum_{k=1}^{L}{c_k\times 2^{L-k}}.(0\le c_k\le 1)\) 为 \(i\) 的二进制展开,若 ,则毒蛇 的第 段是蓝色的,否则是红色的。

每条毒蛇有一个 \(0\) 到 \(9\) 的整数表示它的毒性。给出一个长度为 \(2^L\) 的字符串,其中字符均在 09 的范围内,第 \(i\) 位字符表示第 \(i-1\) 条毒蛇的毒性。

这些毒蛇移动速度非常快,所以他们经常从 JOI 研究所逃跑,因此,研究所附近的住户投诉时常看见从研究所逃出的毒蛇。

研究所整理出了 \(Q\) 天来住户的举报清单,第 \(i\) 天的收到的举报是一个长度为 \(L\) 且仅包含 0, 1, ? 的字符串 。

如果 \(T_d\) 的第 \(j\) 个字符为 0,这意味着逃跑毒蛇的第 段是蓝色的;
如果 \(T_d\) 的第 \(j\) 个字符为 1,这意味着逃跑毒蛇的第 段是红色的;
如果 \(T_d\) 的第 \(j\) 个字符为 ?,这意味着没有人注意到逃跑毒蛇的第 段是什么颜色的。

研究所保证投诉均为准确的信息,并且根据这些信息,JOI 研究所每天会将逃跑的毒蛇全部捕获回来,因此会发生同一条毒蛇在不同日子逃跑的情况。

为了估计逃跑的毒蛇的风险,JOI 实验室的执行主任 K 教授想知道所有可能逃跑的毒蛇的毒性之和。你的任务是编写一个程序,给出 \(Q\) 天的投诉清单,计算每天可能从实验室逃跑的毒蛇的毒性之和。

注意本题空间限制较小。


首先考虑暴力,显然是枚举每一个问号是那一个数字,然后累计即可,那么这样的复杂度是 \(O(2^{cnt2})\),\(cnt2\) 表示问号的个数。

而实际上我们还有另外一种求法,给出的询问实际上可以看做一个高维空间,我们要做的就是统计这个空间中的权值和。那么我们可以用高维前缀和,然后通过容斥得到答案,这样的复杂度是 \(O(2^{cnt1})\) 的,\(cnt1\) 表示 \(1\) 的个数。

同样的,我们可以将数字取反,然后通过和上面类似的方法,把 \(0\) 当做 \(1\) 做一遍,这样的复杂度是 \(O(2^{cnt0})\) ,\(cnt0\) 表示 \(0\) 的个数。

而实际上,根据鸽巢定理我们知道 \(cnt0,cnt1,cnt2\) 最小的不会大于 \(6\)。所以我们取最小的那个并且用它对应复杂度的方法做就好了。

总时间复杂度 \(O(2^n\times n+2^6\times Q)\)。

代码如下:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN =(1<<20)+5;
bool Sunny;
int L,Q,f[MAXN],A[MAXN],B,C[MAXN],D,g[MAXN];
char S[MAXN],T[25];
bool Small;
ll Ans;
ll solve()
{
	int cnt1=0,cnt0=0,cnt2=0;
	int B=0,D=0,num=0,E=0;
	for(int i=0;i<L;++i)
	{
		num<<=1;B<<=1;D<<=1;E<<=1;
		if(T[i]=='1') ++cnt1,B|=1;
		if(T[i]=='?') ++cnt2,D|=1;
		if(T[i]=='0') ++cnt0,E|=1;
	}
	Ans=0;
	if(cnt2<=6)
	{
		for(int i=0;i<L;++i) num=(num<<1)|(T[i]=='?'||T[i]=='1');
		Ans+=A[num];
		for(int i=D;i;i=(i-1)&D)
			Ans+=A[num^i];
	}
	else if(cnt1<=6)
	{
		for(int i=0;i<L;++i) num=(num<<1)|(T[i]=='1'||T[i]=='?');
		Ans=f[num];
		for(int i=B;i;i=(i-1)&B)
		{
			if(C[i]%2==0) Ans+=f[num^i];
			else Ans-=f[num^i];
		}
	}
	else if(cnt0<=6)
	{
		for(int i=0;i<L;++i) num=(num<<1)|(T[i]=='1');
		Ans=g[num];
		for(int i=E;i;i=(i-1)&E)
		{
			if(C[i]%2==0) Ans+=g[num^i];
			else Ans-=g[num^i];
		}
	}
	return Ans;
}
int main()
{
//	cout<<1.0*(&Small-&Sunny)/1024/1024<<"MB"<<endl;
	freopen("d.in","r",stdin);
	freopen("d.out","w",stdout);
	scanf("%d %d",&L,&Q);
	scanf("%s",S);
	for(int i=0;i<(1<<L);++i) C[i]=__builtin_popcount(i);
	for(int i=0;i<(1<<L);++i) f[i]+=S[i]-'0',A[i]=S[i]-'0',g[i]+=S[i]-'0';
	for(int i=0;i<L;++i)
		for(int j=0;j<(1<<L);++j) if((1<<i)&j) f[j]+=f[j^(1<<i)];
	for(int i=0;i<L;++i)
		for(int j=(1<<L)-1;j>=0;--j) if(((1<<i)&j)==0) g[j]+=g[j^(1<<i)];
	while(Q--)
	{
		scanf("%s",T);
		printf("%lld\n",solve());
	}
	return 0;
}

标签:复杂度,研究所,毒蛇,2018,JOI,逃跑,Final,cnt2
来源: https://www.cnblogs.com/nightsky05/p/15563014.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有