codeforces 165E. Compatible Numbers

高維前綴和

題目傳送門

學了一發高維前綴和。

一般我們求多維前綴和是用容斥的,但是當維度很高時會很煩,這時就要用另一種求前綴和的方法。

打個比方,假設我們要求二維前綴和:

for (int i=1;i<=n;i++)
    for (int j=1;j<=m;j++)
        a[i][j]+=a[i][j-1];
for (int i=1;i<=n;i++)
    for (int j=1;j<=m;j++)
        a[i][j]+=a[i-1][j];

這樣就很好寫了。而高維前綴和可以解決關於子集和超集統計的問題(複雜度爲O(n2n)O(n*2^n),而枚舉子集的複雜度爲O(3n)O(3^n)),只要把每一位看作一維進行操作就好了。

對於這道題,當a&amp;b=0a\&amp;b=0時,aa取反後是bb的超集,反之亦然。那麼只需要做一遍高維前綴和就可以求出任意一個超集了。

代碼:

#include<cctype>
#include<cstdio> 
#include<cstring>
#include<algorithm>
#define N 1000005
#define F inline
using namespace std;
int n,a[N],s[1<<22];
F char readc(){
	static char buf[100000],*l=buf,*r=buf;
	if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
	return l==r?EOF:*l++;
}
F int _read(){
	int x=0; char ch=readc();
	while (!isdigit(ch)) ch=readc();
	while (isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=readc();
	return x;
}
int main(){
	n=_read();
	for (int i=1;i<=n;i++) a[i]=_read(),s[~a[i]&(1<<22)-1]=a[i];
	for (int i=0;i<22;i++)
		for (int j=0;j<1<<22;j++)
			if (!(j>>i&1)&&s[j|1<<i]) s[j]=s[j|1<<i];
	for (int i=1;i<=n;i++)
		printf("%d ",s[a[i]]?s[a[i]]:-1);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章