ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

给定n,m,a[0..n-1],b[0..m-1],求sigma i=0..n-1 sigma j=0..m-1 gcd(a[i],b[j]) xor i xor j,多组数据

O(1000000)预处理将每个数分解为三个数之积,且这三个数中任一个满足为质数或小于1000,预处理小于1000的数两两的gcd,即可O(1)求gcd

#include<cstdio>
int t,n,m;
int a[2048],b[2048];
int g[1024][1024];
const int N=1000005;
int v0[N],v1[N],v2[N],mp[N]={0,1};
bool isnp[1000002]={1,1};
int ps[100000],p=0;
inline int read(){
    register int x=0,c=getchar();
    while(c>'9'||c<'0')c=getchar();
    while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
    return x;
}
inline int gcd(int a,int b){
    while(b){int c=a;a=b;b=c%b;}
    return a;
}
int x[3];
inline int gcd1(int a,int b){
    if(!a||!b)return a^b;
    if(a<=1000&&b<=1000)return g[a][b];
    int pp=0;
    if(v0[a]!=1)x[pp++]=v0[a];
    if(v1[a]!=1)x[pp++]=v1[a];
    if(v2[a]!=1)x[pp++]=v2[a];
    int ans=1,d;
    for(int i=0;i<pp;i++){
        d=x[i]<=1000?g[x[i]][b%x[i]]:b%x[i]?1:x[i];
        ans*=d;
        b/=d;
    }
    return ans;
}
int main(){
    for(int i=0;i<=1000;i++)for(int j=i;j<=1000;j++)g[i][j]=g[j][i]=gcd(i,j);
    for(int i=2;i<=1000000;i++){
        if(!isnp[i])ps[p++]=i,mp[i]=i;
        for(int j=0,k;(k=i*ps[j])<=1000000;j++){
            isnp[k]=1;
            if(i%ps[j]==0){
                mp[k]=mp[i];
                break;
            }
            mp[k]=ps[j];
        }
    }
    v0[1]=v1[1]=v2[1]=1;
    for(int i=2;i<=1000000;i++){
        int j=i/mp[i];
        v0[i]=v0[j];v1[i]=v1[j];v2[i]=v2[j];
        if(v0[i]*mp[i]<=1000)v0[i]*=mp[i];
        else if(v1[i]*mp[i]<=1000)v1[i]*=mp[i];
        else v2[i]*=mp[i];
    }
    t=read();
    while(t--){
        n=read();
        m=read();
        for(int i=0;i<n;i++)a[i]=read();
        for(int i=0;i<m;i++)b[i]=read();
        unsigned int ans=0;
        for(int i=0;i<n;i++)for(int j=0;j<m;j++)ans+=gcd1(a[i],b[j])^i^j;
        printf("%u\n",ans);
    }
    return 0;
}

 

posted on 2016-03-25 18:49  nul  阅读(405)  评论(0编辑  收藏  举报