第一行输入一个正整数T(T<=85),表示测试数据的组数。
每组数据第一行包含两个正整数n,m(1<=n,m<=2000),表示序列的长度。
第二行包含n个正整数,表示a[0],a[1],...,a[n-1](0<=a[i]<=1000000)。
第三行包含m个正整数,表示b[0],b[1],...,b[m-1](0<=b[i]<=1000000)。
利用暴力预处理出之间的gcd,复杂度为l
然后利用欧拉筛的原理把任意数拆成3个不大于的因子,然后每次求gcd(x,y)只要枚举x的三个因子和y的关系就好了。
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int maxn = 1010;
namespace Input{
const int BUF = 65536;
char buf[BUF + 1];
char *head = buf, *tail = buf;
}
inline char inputchar(){
using namespace Input;
if(head == tail)
*(tail = (head = buf) + fread(buf, 1, BUF, stdin)) = 0;
return *head++;
}
inline void io(int &ret){
char ch = inputchar();
while(ch < '0' || ch > '9')ch = inputchar();
ret = ch - '0';ch = inputchar();
while(ch >= '0' && ch <= '9'){
ret = ret * 10 + ch - '0';
ch = inputchar();
}
}
int t,n,m,cnt,res[maxn][maxn],x[2*maxn],y[2*maxn],pri[maxn*maxn],num[maxn*maxn][3];
ll ans;
inline void up(int k,int val){
int P=1000;
if (num[k][0]*val<=P)num[k][0]*=val;
else if (num[k][1]*val<=P)num[k][1]*=val;
else num[k][2]*=val;
}
void init(){
int P=1000;
for(int i=0;i<=P;++i)
res[i][0]=res[0][i]=res[i][i]=i;
for(int i=1;i<=P;++i)
for(int j=1;j<i;++j)
res[i][j]=res[j][i]=res[j][i%j];
P*=P;
num[1][0]=num[1][1]=num[1][2]=1;
for(int i=2;i<=P;++i){
//cout<<i<<endl;
if(!num[i][0]){
pri[cnt++]=i;
num[i][0]=i;
num[i][1]=num[i][2]=1;
}
for(int j=0;j<cnt&&i*pri[j]<=P;++j){
memcpy(num[i*pri[j]],num[i],sizeof num[i]);
up(i*pri[j],pri[j]);
if(i%pri[j]==0)break;
}
}
}
inline int gcd(int u,int v){
int P=1000,ans=1,fa,tmp;
if(!u||!v)return u|v;
if(u<=P&&v<=P)return res[u][v];
for(int i=0;i<3;++i){
if(num[u][i]>1){
fa=num[u][i];
if(fa<=P)tmp=res[fa][v%fa];
else tmp=(v%fa)?1:fa;
ans*=tmp,v/=tmp;
}
}
return ans;
}
int main(){
init();
for(io(t);t--;){
unsigned ans=0;io(n),io(m);
for(int i=0;i<n;++i)io(x[i]);
for(int i=0;i<m;++i)io(y[i]);
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);
}
}