原题解链接:https://ac.nowcoder.com/discuss/157310

由题面可知 t=f(x)\ t=f(x)没有平方根,加上xx的最大质因子为7171,说明它的质因子种数只有2020种。 那么 t=f(x)\ t=f(x)可映射成一个2020位的二进制数。 即 t=p0b0+p1b1+...+pkbkt=p_{0}*b_{0}+p_{1}*b_{1}+...+p_{k}*b_{k}

其中  pi\ p_{i} 为第 i \ i大的素数, bi\ b_{i} 为第 i\ i位二进制位, 我们不妨设bin(t)=pk...p1p0 bin(t) = p_{k}...p_{1}p_{0}

bin(g(f(x1),f(x2),f(x3)))=bin(f(x1))bin(f(x2))bin(f(x3)) bin(g(f(x_{1}),f(x_{2}),f(x_{3}))) = bin(f(x_{1}))\oplus bin(f(x_{2})) \oplus bin(f(x_{3}))

那么对于 z\ z来说,它的表示方法的种数有 num(z)=ijk=bin(z)An[i]Bn[j]Cn[k]num(z) = \sum_{i \oplus j \oplus k=bin(z)}{An[i]*Bn[j]*Cn[k]} 其中  An[i]\ An[i] AA数组中经过binbin映射后等于i的个数,  Bn[j]\ Bn[j]BB数组中经过binbin映射后等于jj的个数, Cn[k]\ Cn[k]CC数组中经过binbin映射后等于kk的个数。

这里再用卷积加速即可。


#include <stdio.h>
#define rep(i, j, k) for(int i = (j); i <= (k); ++i)
typedef long long ll;
const int MOD = 1e9 + 7;
const int rev = (MOD + 1) / 2;
int p[105], a[3][(1 << 22)];
void FWT(int a[],int n){
    for(int d=1;d<n;d<<=1)
        for(int m=d<<1,i=0;i<n;i+=m)
            for(int j=0;j<d;j++){
                int x=a[i+j],y=a[i+j+d];
				a[i+j]=(x+y)%MOD,a[i+j+d]=(x-y+MOD)%MOD;
            }
}
void UFWT(int a[], int n) {
    for(int d=1;d<n;d<<=1)
        for(int m=d<<1,i=0;i<n;i+=m)
            for(int j=0;j<d;j++){
                int x=a[i+j],y=a[i+j+d];
				a[i+j]=1ll*(x+y)*rev%MOD,a[i+j+d]=(1ll*(x-y+MOD)%MOD*rev%MOD)%MOD;
            }
}
void solve(int a[],int b[],int n){
    FWT(a,n);
    FWT(b,n);
    for(int i=0;i<n;i++) a[i]=1LL*a[i]*b[i]%MOD;
    UFWT(a,n);
}
int main(){
	int c = 0;
	rep(i, 2, 71){
		bool flag = true;
		rep(j, 2, i - 1) if(i % j == 0) flag = false;
		if(flag) p[c++] = i;
	}
	int n; scanf("%d", &n);
	rep(k, 0, 2) rep(i, 1, n){
		ll t; scanf("%lld", &t);
		int x = 0; rep(j, 0, c-1) if(t % p[j] == 0) x |= (1 << j);
		a[k][x]++;
//		printf("t:%lld x:%d\n", t, x);
	}
//	rep(k, 0, 2) rep(j, 0, 1<<c) printf("%d%c", a[k][j], " \n"[j==(1<<c)]);
	solve(a[0], a[1], (1 << c));
//	rep(k, 0, 2) rep(j, 0, 1<<c) printf("%d%c", a[k][j], " \n"[j==(1<<c)]);
	solve(a[0], a[2], (1 << c));
//	rep(k, 0, 2) rep(j, 0, 1<<c) printf("%d%c", a[k][j], " \n"[j==(1<<c)]);
	int ans = 0;
	rep(i, 0, (1 << c) - 1){
		int x = 1;
		rep(j, 0, c - 1) if(i >> j & 1) x = (ll)x * p[j] % MOD;
//		if(a[0][i]) printf("x:%d c:%d\n", x, a[0][i]);
		ans = (ans + (ll)x * a[0][i] % MOD) % MOD;
	}
	printf("%d\n", ans);
	return 0;

}