NOI模拟 序列
涉及知识点:数论,图论转化建图
题意
有一串长为 \(n\ (\leq10^3)\) 序列 \(a\),给出 \(m\ (\leq10^3)\) 个条件,每条条件形如 \(\gcd(a_i,a_j)=k\),问是否存在这样的序列满足所有条件。保证不存在重复的 \((a_i,a_j)\) 对。
思路
把题目给出的所有关系建成图,点 \(i\) 代表 \(a_i\),\(\gcd(a_i,a_j)=k\) 转化为 \(i\) 连 \(j\) 边权为 \(k\) 的边。将每个节点的点权设为与它相连的所有边边权的最小公倍数,可以证明,假如条件合法,这将是最小的合法值。
然后再遍历每条边,记为 \((u,v,k)\),判断 \(u\) 和 \(v\) 点权的 \(\gcd\) 是否为 \(k\),可以发现:
- 如果 \(k<\gcd\),因为 \(u\) 和 \(v\) 的点权已经是最小,无法再变小,因此它们的 \(\gcd\) 也不可能再变小,该情况不合法。
- 如果 \(k=\gcd\),该情况符合题意,合法。
- 如果 \(k>\gcd\),不存在这种情况,因为 \(u\) 和 \(v\) 的点权都为 \(k\) 的倍数,它们的 \(\gcd\) 无论如何都不可能小于 \(k\)。
因此,判断每条边即可。
代码
代码似乎会爆精度,莫名其妙就过了,有bug慎阅
#include<bits/stdc++.h>
using namespace std;
#ifdef ONLINE_JUDGE
#define getchar __getchar
inline char __getchar(){
static char ch[1<<20],*l,*r;
return (l==r&&(r=(l=ch)+fread(ch,1,1<<20,stdin),l==r))?EOF:*l++;
}
#endif
template<class T>inline void rd(T &x){
T res=0,f=1;
char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-')f=-1; ch=getchar();}
while('0'<=ch && ch<='9'){res=res*10+ch-'0';ch=getchar();}
x=res*f;
}
template<class T>inline void wt(T x,char endch='\0'){
static char wtbuff[20];
static int wtptr;
if(x==0){
putchar('0');
}
else{
if(x<0){x=-x;putchar('-');}
wtptr=0;
while(x){wtbuff[wtptr++]=x%10+'0';x/=10;}
while(wtptr--) putchar(wtbuff[wtptr]);
}
if(endch!='\0') putchar(endch);
}
typedef long long LL;
typedef __int128_t int128;
const int MAXN=1e3+5;
int n,m,head[MAXN],ecnt=1;
int128 val[MAXN];
struct EDGE{
int v,nxt;
int128 w;
}e[MAXN<<2];
inline void add(const int& u,const int& v,const int128& w){
e[++ecnt].v=v;
e[ecnt].w=w;
e[ecnt].nxt=head[u];
head[u]=ecnt;
}
inline int128 __lcm(int128 x,int128 y){
return x*y/__gcd(x,y);
}
inline void solve(){
memset(head,0,sizeof(head));
ecnt=1;
rd(n);rd(m);
for(int i=1,u,v;i<=m;i++){
int128 w;
rd(u);rd(v);rd(w);
add(u,v,w);add(v,u,w);
}
for(int i=1;i<=n;i++){
val[i]=1;
for(int j=head[i];j;j=e[j].nxt){
val[i]=__lcm(val[i],e[j].w);
}
}
for(int i=2;i<=ecnt;i+=2){
if(__gcd(val[e[i].v],val[e[i^1].v])!=e[i].w){
puts("No");
return;
}
}
puts("Yes");
}
int main(){
int t;
rd(t);
while(t--) solve();
return 0;
}