题意

其中a[i]<=2ka[i]<=2^ka[i]<=2k ,n∗k<=2e6n*k<=2e6n∗k<=2e6,x==3x==3x==3
数据分治
对于k较大的情况,可以n2∗kn^2*kn2∗k暴力,这里可以用手写bitset优化
这里因为不知道n,k所以使用不定长数组(其实和vector一样)
tips:tips:tips:不定长数组其实是一个指针数组,需要先手动赋初值才能正常使用.
对于k较小的情况,考虑这个3次方的贡献:
枚举3个位置,钦定这些位置异或出的结果都为1.计算满足条件的方案数
考虑它们的异或结果,其实只有8种(我们最后计算的时候只枚举4种的原因是我们需要另一个方案使得两种方案异或起来每个位置都是1,所以另外4种已经被算过了).
然后我们可以在输入时求出每种异或方案的个数.
现在计算满足条件的方案数:
这里的coe表示位置摆放顺序的方案数,因为h中记录的只是方案数,没有记录顺序.
这个复杂度是n∗k3n*k^3n∗k3的
#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);
}
本文深入探讨了数据分治算法的应用,特别是在处理大规模数据集时的优化策略。针对不同规模的问题,介绍了暴力解法和手写bitset优化技巧,以及如何通过枚举和计算异或方案数来解决特定问题。文章还提供了详细的代码实现,展示了如何根据数据规模选择最优算法。

1142

被折叠的 条评论
为什么被折叠?



