一道bitset练习题

题意

在这里插入图片描述
其中 a [ i ] < = 2 k a[i]<=2^k , n k < = 2 e 6 n*k<=2e6 , x = = 3 x==3
数据分治
对于k较大的情况,可以 n 2 k n^2*k 暴力,这里可以用手写bitset优化
这里因为不知道n,k所以使用不定长数组(其实和vector一样)
t i p s : tips: 不定长数组其实是一个指针数组,需要先手动赋初值才能正常使用.
对于k较小的情况,考虑这个3次方的贡献:
枚举3个位置,钦定这些位置异或出的结果都为1.计算满足条件的方案数
考虑它们的异或结果,其实只有8种(我们最后计算的时候只枚举4种的原因是我们需要另一个方案使得两种方案异或起来每个位置都是1,所以另外4种已经被算过了).
然后我们可以在输入时求出每种异或方案的个数.
现在计算满足条件的方案数:
这里的coe表示位置摆放顺序的方案数,因为h中记录的只是方案数,没有记录顺序.
这个复杂度是 n k 3 n*k^3

#include<bits/stdc++.h>
using namespace std;
#define ull unsigned long long
const int maxn=2e6+5;
const int mod=998244353;
inline int read(){
	char c=getchar();int t=0,f=1;
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){t=(t<<3)+(t<<1)+(c^48);c=getchar();}
	return t*f;
}
int n,k,x;
unsigned int seed;
unsigned int get01(){
	seed^=seed<<13;
	seed^=seed>>17;
	seed^=seed<<5;
	return seed&1;
}
unsigned int *a[maxn],b[maxn];
inline int am(int x){
	return x>=mod?x-mod:x;
}
int pre[maxn];
inline int ksm(int a,int b){
	int ans=1;
	while(b){
		if(b&1)ans=1ll*ans*a%mod;
		a=1ll*a*a%mod;b>>=1;
	}
	return ans;
}
int g[maxn],h[60][60][60][8];
signed main(){
	n=read(),k=read(),x=read();
	scanf("%u",&seed);
	if(k>=60){
		int len=(k-1)/32+1;
		for(int i=1;i<=n;i++){
			a[i]=b+i*len;
			for(int j=0;j<k;j++){
				if(get01()){
					a[i][j>>5]=a[i][j>>5]+(1u<<(j%32));
				}
			}
		}
		pre[0]=1;
		for(int i=1;i<=len;i++)pre[i]=ksm(2,i*32);
		unsigned int ans=0;
		for(int i=1;i<=n;i++){
			for(int j=i+1;j<=n;j++){
				unsigned int tmp=0;
				for(int k=0;k<len;k++){
					tmp=am(tmp+(ull)(a[i][k]^a[j][k])*pre[k]%mod);
					//printf("%d %u %u %d %u\n",k,a[i][k],a[j][k],pre[k],tmp);
				}
				ans=am(ans+1ll*tmp*tmp%mod*tmp%mod);
			}
		}
		printf("%u\n",ans);
		return 0;
	}
	int ans=0;
	pre[0]=1;
	for(int i=1;i<=n;i++)pre[i]=2ll*pre[i-1]%mod;
	for(int i=1;i<=n;i++){
		for(int j=0;j<k;j++)
		g[j]=get01();
		for(int k1=0;k1<k;k1++)
		for(int k2=k1;k2<k;k2++)
		for(int k3=k2;k3<k;k3++){
			//printf("%d %d %d %d\n",k1,k2,k3,g[k1]|(g[k2]<<1)|(g[k3]<<2));
			h[k1][k2][k3][g[k1]|(g[k2]<<1)|(g[k3]<<2)]++;
		}
	}
	for(int k1=0;k1<k;k1++){
		for(int k2=k1;k2<k;k2++){
			for(int k3=k2;k3<k;k3++){
				for(int r=0;r<4;r++){
					int q=7^r,coe=1;
					if((k1!=k2)&&(k2!=k3))coe=6;
					else if((k1!=k2)||(k2!=k3))coe=3;
					coe=1ll*coe*h[k1][k2][k3][q]%mod*h[k1][k2][k3][r]%mod;
					ans=am(ans+1ll*pre[k1]*pre[k2]%mod*pre[k3]%mod*coe%mod);
				}
			}
		}
	}
	printf("%d\n",ans%mod);
}
发布了62 篇原创文章 · 获赞 1 · 访问量 985

猜你喜欢

转载自blog.csdn.net/wmhtxdy/article/details/103875665