「JOI2018」Snake Escaping 题解

思维定势属于是,怎么又被 \(2^L,Q\) 之类的东西搞乱了啊。

首先根据鸽巢原理,一个询问中出现次数最小的字符出现次数最多是 \(\lfloor \frac{L}{3} \rfloor\) 嘛,然后分类考虑:

  • 如果这个字符是 ?:那很好办,暴力枚举 ? 分别代表什么就好了;
  • 否则,
    • 如果这个字符是 \(0\):我们将 \(0\) 看作这一位是 ? 的答案减去这一位是 \(1\) 的答案;
    • 如果这个字符是 \(1\):跟上面的差不多。

现在构建出一个大致的框架,我们思考出现次数最少的字符是 \(0\) 怎么做。

考虑容斥,答案就是没有 \(0\) 转成 \(1\) 的方案数,减去有一个 \(0\) 转成 \(1\) 的方案数,加上有两个 \(0\) 转成 \(1\) 的方案数……容易发现枚举哪些 \(0\) 变成了 \(1\) 的时间复杂度是 \(O(2^{p})\)(其中 \(p\)\(0\) 的个数)。

然后现在的问题是,我们确定了一些位置是 \(1\),另外一些位置可以随便填的答案。记确定的位置的状态为 \(S\),我们要求的就是编号为 \(S\) 的超集的蛇毒性和。高维前缀和就可以做到 \(O(1) \times O(2^{p}) = O(2^{p})\)

最后是出现次数最少的字符是 \(1\) 怎么做。沿用上面的方法变成一个求子集和的问题,也可以用高维前缀和来处理。

具体实现可以采用 FMT/FWT 实现,代码里用的是 FWT。

/*
他决定要“格”院子里的竹子。于是他搬了一条凳子坐在院子里,面对着竹子硬想了七天,结果因为头痛而宣告失败。
DONT NEVER AROUND . //
*/
#include<bits/stdc++.h>
using namespace std;
int l,q;
void FWT_or(int *f){for(int o=2,k=1;o<=(1<<l);o<<=1,k<<=1)	for(int i=0;i<(1<<l);i+=o)	for(int j=0;j<k;++j)	f[i+j+k]+=f[i+j];}
void FWT_and(int *f){for(int o=2,k=1;o<=(1<<l);o<<=1,k<<=1)	for(int i=0;i<(1<<l);i+=o)	for(int j=0;j<k;++j)	f[i+j]+=f[i+j+k];}
int f[(1<<20)+5],g[(1<<20)+5],a[(1<<20)+5];
char s[(1<<20)+5],snk[25];
int cq[25],c0[25],c1[25],pq,p0,p1;
int dfs(int S,int p)
{
	if(p==pq)	return a[S];
	return dfs(S,p+1)+dfs(S|(1<<cq[p]),p+1);
}
int dfs0(int S,int p)
{
	if(p==p0)	return g[S];
	return dfs0(S,p+1)-dfs0(S|(1<<c0[p]),p+1);
}
int dfs1(int S,int p)
{
	if(p==p1)	return f[S];
	return dfs1(S|(1<<c1[p]),p+1)-dfs1(S,p+1);
}
int main(){
	scanf("%d %d",&l,&q);
	scanf("%s",s);
	for(int i=0;i<(1<<l);++i)	f[i]=g[i]=a[i]=(s[i]-'0');
	FWT_or(f),FWT_and(g);
	while(q-->0)
	{
		scanf("%s",snk);
		reverse(snk,snk+l);
		pq=p0=p1=0;
		int S0=0,S1=0;
		for(int i=0;i<l;++i)
		{
			if(snk[i]=='?')	cq[pq++]=i,S0|=(1<<i);
			if(snk[i]=='0')	c0[p0++]=i;
			if(snk[i]=='1')	c1[p1++]=i,S1|=(1<<i);
		}
		int st=min({pq,p0,p1}),ans;
		if(st==pq)	ans=dfs(S1,0);
		else if(st==p0)	ans=dfs0(S1,0);
		else	ans=dfs1(S0,0);
		printf("%d\n",ans);
	}
	return 0;
}
posted @ 2022-05-05 17:06  SyadouHayami  阅读(33)  评论(0编辑  收藏  举报

My Castle Town.