Wannafly Winter Camp Day8(Div1, onsite)
I题 岸边露伴的人生经验
有点无聊,写点博客打发时间吧。
就按照题解所说的,把它转化成一个20位的二进制数。记录这
n
n
n个数
(
<
2
20
)
(<2^{20})
(<220)的出现次数,对这个数组套个fwt的板子。两个向量距离的平方最大为40,算一下每种距离二元组的数量,然后分别算贡献就行了。注意一下四元组是和顺序有关系的,本题就没有了。
AC_code
#include<bits/stdc++.h>
#define clr(a, b) memset(a,b,sizeof((a)))
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
typedef long long LL;
const int MXN = 3e5 + 7;
const int MOD = 998244353;
int n, m, Q;
int LN;
LL ar[1<<21], br[MXN], inv2;
LL ksm(LL a, int b) {
LL res = 1;
for(; b; b>>=1, a=a*a%MOD) {
if(b&1) res = res * a % MOD;
}
return res;
}
void FWT_xor(LL *a,int LN,int opt) {
for(int i=1;i<LN;i<<=1)
for(int p=i<<1,j=0;j<LN;j+=p)
for(int k=0;k<i;++k) {
LL X=a[j+k],Y=a[i+j+k];
a[j+k]=(X+Y)%MOD;a[i+j+k]=(X+MOD-Y)%MOD;
if(opt==-1)a[j+k]=a[j+k]*inv2%MOD,a[i+j+k]=a[i+j+k]*inv2%MOD;
}
}
int main() {
inv2 = ksm(2, MOD - 2);
scanf("%d", &n);
for(int i = 0, tmp; i < n; ++i) {
tmp = 0;
for(int j = 0, x; j < 10; ++j) {
scanf("%d", &x);
if(x == 0) tmp <<= 2;
else if(x == 1) tmp <<= 2, tmp |= 1;
else tmp <<= 1, tmp |= 1, tmp <<= 1;
}
++ ar[tmp];
}
LN = (1<<20);
FWT_xor(ar, LN, 1);
for (int i = 0; i < LN; ++i) ar[i] = ar[i] * ar[i] % MOD;
FWT_xor(ar, LN, -1);
//ar[x] 表示有多少对ai和aj异或结果为x
LL ans = 0;
for(int i = 0, tmp, cnt; i < LN; ++i) {
tmp = i; cnt = 0;
for(int j = 0, x; j < 10; ++j) {
x = tmp & 3;
if(x == 3) x = 1;
if(x == 2) x = 4;
cnt += x;
tmp >>= 2;
}
br[cnt] = (br[cnt] + ar[i]) % MOD;
}
for(int i = 0; i <= 40; ++i) {
ans = (ans + br[i]*br[i]%MOD)%MOD;
}
printf("%lld\n", ans);
return 0;
}
fwt模板
void FWT_or(int *a,int LN,int opt) {
for(int i=1;i<LN;i<<=1)
for(int p=i<<1,j=0;j<LN;j+=p)
for(int k=0;k<i;++k)
if(opt==1)a[i+j+k]=(a[j+k]+a[i+j+k])%MOD;
else a[i+j+k]=(a[i+j+k]+MOD-a[j+k])%MOD;
}
void FWT_and(int *a,int LN,int opt) {
for(int i=1;i<LN;i<<=1)
for(int p=i<<1,j=0;j<LN;j+=p)
for(int k=0;k<i;++k)
if(opt==1)a[j+k]=(a[j+k]+a[i+j+k])%MOD;
else a[j+k]=(a[j+k]+MOD-a[i+j+k])%MOD;
}
void FWT_xor(int *a,int LN,int opt) {
for(int i=1;i<LN;i<<=1)
for(int p=i<<1,j=0;j<LN;j+=p)
for(int k=0;k<i;++k) {
int X=a[j+k],Y=a[i+j+k];
a[j+k]=(X+Y)%MOD;a[i+j+k]=(X+MOD-Y)%MOD;
if(opt==-1)a[j+k]=1ll*a[j+k]*inv2%MOD,a[i+j+k]=1ll*a[i+j+k]*inv2%MOD;
}
}
void FWT_and(ll *P,int LN,int opt) {
for(int i=2;i<=LN;i<<=1)
for(int p=i>>1,j=0;j<LN;j+=i)
for(int k=j;k<j+p;++k)
P[k]+=P[k+p]*opt;
}
void FWT_or(ll *P,int LN,int opt) {
for(int i=2;i<=LN;i<<=1)
for(int p=i>>1,j=0;j<LN;j+=i)
for(int k=j;k<j+p;++k)
P[k+p]+=P[k]*opt;
}
void FWT_xor(int *P,int LN,int opt) {
for(int i=2;i<=LN;i<<=1)
for(int p=i>>1,j=0;j<LN;j+=i)
for(int k=j;k<j+p;++k) {
int x=P[k],y=P[k+p];
P[k]=(x+y)%MOD;P[k+p]=(x-y+MOD)%MOD;
if(opt==-1)P[k]=1ll*P[k]*inv2%MOD,P[k+p]=1ll*P[k+p]*inv2%MOD;
}
}