【BZOJ4454】C Language Practice

Description
这里写图片描述

Input

第一行输入一个正整数T(T<=85),表示测试数据的组数。
每组数据第一行包含两个正整数n,m(1<=n,m<=2000),表示序列的长度。
第二行包含n个正整数,表示a[0],a[1],…,an-1
第三行包含m个正整数,表示b[0],b[1],…,bm-1
Output

对于每组数据输出一行一个整数,即答案。
Sample Input

3

3 2

5 9 6

3 4

2 2

8 9

0 6

1 1

9

6
Sample Output

6

22

3

HINT

Source

Claris出的论文题.
卡常数,要求O(1) gcd
毁我青春,颓我人生.
在写这个题的过程中收了最少10个弗拉格.
我真是弗拉格大师,连立带收,一条龙服务.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 1000000
#define GET (ch>='0'&&ch<='9')
using namespace std;
int T,n,m,a[2010],b[2010];
unsigned ans;
int t=1000,maxn=1000000;
int d[MAXN+10][4];
int Gcd[1010][1010];
int prime[200000],top;
bool not_prime[MAXN+10];
void check()
{
    for (int i=0;i<=t;i++)   Gcd[0][i]=Gcd[i][0]=Gcd[i][i]=i;
    for (int i=2;i<=t;i++)  for (int j=1;j<i;j++)   Gcd[i][j]=Gcd[j][i]=Gcd[i-j][j];
    d[1][0]=d[1][1]=d[1][2]=1;
    for (int i=2;i<=maxn;++i)
    {
        if (!not_prime[i])  prime[++top]=i,d[i][0]=i,d[i][1]=d[i][2]=1;
        for (int j=1;j<=top&&i*prime[j]<=maxn;++j)
        {
            int tmp=i*prime[j];not_prime[tmp]=1;
            d[tmp][0]=d[i][0];d[tmp][1]=d[i][1];d[tmp][2]=d[i][2];
            if (d[tmp][0]*prime[j]<=t)   d[tmp][0]*=prime[j];
            else    if (d[tmp][1]*prime[j]<=t)   d[tmp][1]*=prime[j];
            else    d[tmp][2]*=prime[j];
            if (i%prime[j]==0)  break;
        }
    }
}
inline void in(int &x)
{
    char ch=getchar();x=0;
    while (!GET)    ch=getchar();
    while (GET) x=x*10+ch-'0',ch=getchar();
}
inline int Getgcd(int x,int y)
{
    if (!x||!y) return x+y;
    int ret=1,tmp,temp;
    for (int i=0;i<3;++i)
    {
        tmp=d[x][i];
        if (tmp<=t)  temp=Gcd[tmp][y%tmp];
        else    if (y%tmp==0)   temp=tmp;
        else    temp=1;
        ret*=temp;y/=temp;
    }
    return ret;
}
int main()
{
    check();
    for (in(T);T;T--)
    {
        ans=0;in(n);in(m);
        for (int i=0;i<n;++i)    in(a[i]);
        for (int j=0;j<m;++j)    in(b[j]);
        for (int i=0;i<n;++i)    for (int j=0;j<m;++j)    ans+=Getgcd(a[i],b[j])^i^j;
        printf("%u\n",ans);
    }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值