将满足题意的(i,j),(p,q)预处理出来,然后向质因子连边跑网络流即可。
被坑了一下午,这样写常数巨大。改成define就过了……
题面:https://www.nowcoder.com/acm/contest/130/D
代码:
//include <bits/stdc++.h>
#pragma GCC optimize(2)
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
#include <map>
#include <cmath>
#include <cstring>
#define db double
#define LL long long
//#define int LL
#define rep(i,x,y) for (int i=x;i<=y;++i)
using namespace std;
const int N = 504;
//const int mod = /;
const int INF =1<<30;
void read(int &x)
{
int f=1;
x=0;
char ch=getchar();
while (!isdigit(ch)) (ch=='-'?f=-1:0),ch=getchar();
while ( isdigit(ch)) x=x*10+ch-'0',ch=getchar();
x*=f;
return ;
}
struct xx
{
int V,next,cap;
}bb[N*N*20];
int c[N*N*10];
int G,head[N*N*10],cur[N*N*10];
void add(int x,int y,int z)
{
bb[++G]=(xx){y,head[x],z};
head[x]=G;
bb[++G]=(xx){x,head[y],0};
head[y]=G;
}
int S,T;//queue <int > q;
int q[N*N*10];
int level[N*N*10];
inline int BFS()
{
int hd=1,tl=1;
//q.push(S);
q[1]=S;
memset(level,0,sizeof(level));
level[S]=1;
while (hd<=tl)
{
int u=q[hd];++hd;
for (int i=head[u];i;i=bb[i].next)
{
int v=bb[i].V;
if (bb[i].cap&&!level[v]) level[v]=level[u]+1,q[++tl]=v;
}
}
return level[T];
}
int dfs(int x,int a)
{
if (x==T||a==0) return a;
int flow=0,f;
for (int &i=cur[x];i;i=bb[i].next)
{
#define v bb[i].V
if (level[v]==level[x]+1&&bb[i].cap&&(f=dfs(v,min(bb[i].cap,a)))<=a)
{
a-=f;
flow+=f;
bb[i].cap-=f;
bb[i^1].cap+=f;
if (a==0) break;
}
}
return flow;
}
int cnt;
int Dinic()
{
int flow=0;
while (BFS())
{
rep(i,1,cnt) cur[i]=head[i];
flow+=dfs(S,INF);
}
return flow;
}
int tp[2],t,n,a[N],b[N];
int gcd(int x,int y)
{
return y?gcd(y,x%y):x;
}
int s[2][N*N],Q;
int pri[32000],mn[32000];
void mk_tb(int n,int *p)
{
rep(i,2,n)
{
if (!mn[i]) p[mn[i]=++*p]=i;
for (int j=1;j<=mn[i]&&(LL)i*p[j]<=n;++j) mn[i*p[j]]=j;
}
}
map <int,int >id;
signed main()
{
// freopen("data.txt","r",stdin);
// freopen("Moon.txt","w",stdout);
read(Q);
mk_tb(32000,pri);
while (Q--)
{
id.clear();
cnt=tp[1]=tp[0]=t=0;
G=1;
memset(head,0,sizeof(head));
read(n);
rep(i,1,n) read(a[i]);
rep(i,1,n) read(b[i]);
rep(i,1,n)
rep(j,1,n)
{
int tmp=gcd(a[i],b[j]);
if (a[i]<b[j]&&tmp>1) ++cnt,s[0][++tp[0]]=cnt,c[cnt]=tmp;
if (a[i]>b[j]&&tmp>1) ++cnt,s[1][++tp[1]]=cnt,c[cnt]=tmp;
}
S=++cnt,T=++cnt;
rep(i,1,tp[0])
{add(S,s[0][i],1);
int tmp=sqrt(c[s[0][i]]);
int k=c[s[0][i]];
for (int j=1;pri[j]<=k&&pri[j]<=tmp&&j<=pri[0];++j)
if (k%pri[j]==0)
{
if (!id.count(pri[j])) id[pri[j]]=++cnt;
add(s[0][i],id[pri[j]],1);
while (k%pri[j]==0) k/=pri[j];
}
if (k>1)
{
if (!id.count(k)) id[k]=++cnt;
add(s[0][i],id[k],1);
}
}
rep(i,1,tp[1])
{ add(s[1][i],T,1);
int tmp=sqrt(c[s[1][i]]);
int k=c[s[1][i]];
for (int j=1;pri[j]<=tmp&&pri[j]<=k&&j<=pri[0];++j)
if (k%pri[j]==0)
{
if (id.count(pri[j])) //continue;//id[pri[j]]=++cnt;
add(id[pri[j]],s[1][i],1);
while (k%pri[j]==0) k/=pri[j];
}
if (k>1)
{
if (id.count(k))// id[k]=++cnt;
add(id[k],s[1][i],1);
}
}
printf("%d\n",Dinic());
}
return 0;
}