此题卡常卡空间。。
有一种O(n)-O(1)的Gcd:对于一个数n,它可以分解成a*b*c,(a,b,c为质数或小于sqrt(n)),证明略。
然后预处理1~n每个数的分解方式和0~sqrt(n)两两的Gcd,询问即可O(1)。
真是慢的飞起。。
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 1005
#define S 1000
using namespace std;
int n,m,cnt,Ans,x[2005],y[2005],T;
int a[N][N],de[N*N][3],p[N*N],t,t1;
int read()
{
int x=0;char ch=getchar();
while (ch<'0' || ch>'9') ch=getchar();
while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
void up(int a[3],int c)
{
if (a[0]*c<=S) a[0]*=c;
else if (a[1]*c<=S) a[1]*=c;
else a[2]*=c;
}
void pre(int n)
{
for (int i=0;i<=n;i++)
a[i][0]=a[0][i]=a[i][i]=i;
for (int i=1;i<=n;i++)
for (int j=1;j<i;j++)
a[i][j]=a[j][i]=a[j][i%j];
int m=n*n;
de[1][0]=de[1][1]=de[1][2]=1;
for (int i=2;i<=m;i++)
{
if (!de[i][0])
{
p[++cnt]=i;
de[i][0]=i,de[i][1]=de[i][2]=1;
}
for (int j=1;j<=cnt&&i*p[j]<=m;j++)
{
memcpy(de[i*p[j]],de[i],sizeof de[i]);
up(de[i*p[j]],p[j]);
if (i%p[j]==0) break;
}
}
}
int Gcd(int x,int y)
{
if (!x||!y) return x|y;
if (x<=S&&y<=S) return a[x][y];
int d=1;
for (int i=0;i<3;i++)
if (de[x][i]>1)
{
t1=de[x][i];
if (t1<=S) t=a[t1][y%t1];
else t=(y%t1)?1:t1;
d*=t,y/=t;
}
return d;
}
int main()
{
pre(S);T=read();
while (T--)
{
Ans=0;n=read();m=read();
for (int i=0;i<n;i++) x[i]=read();
for (int i=0;i<m;i++) y[i]=read();
for (int i=0;i<n;i++)
for (int j=0;j<m;j++)
Ans+=Gcd(x[i],y[j])^i^j;
printf("%u\n",Ans);
}
return 0;
}