[数论] LOJ #508. 「LibreOJ NOI Round #1」失控的未来交通工具

来源:互联网 发布:软件项目管理方法 编辑:程序博客网 时间:2024/06/06 07:41

这种非简单路 一般转化成任意一条路加上若干环
这里大概是任意一条路加上若干环长的gcd
任意一条路 可以弄出任意一颗生成树? 但是这里实际上只需要一个带权并查集
详见官方题解

#include<cstdio>#include<cstdlib>#include<algorithm>using namespace std;typedef long long ll;typedef pair<ll,ll> abcd;inline char nc(){  static char buf[100000],*p1=buf,*p2=buf;  return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}inline void read(int &x){  char c=nc(),b=1;  for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;  for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;}const int N=1000005;inline abcd GCD(ll a,ll b){  if (!b) return abcd(1,0);  abcd t=GCD(b,a%b);  return abcd(t.second,t.first-a/b*t.second);}inline ll calc(ll a,ll b,ll n){  abcd G=GCD(a,n); ll d=a*G.first+n*G.second;  if (b%d) return -1;  return (G.first*(b/d)%(n/d)+(n/d))%(n/d);}int n,m,Q;int fat[N]; int g[N],dis[N];inline int Fat(int u){  if (u==fat[u]) return u;  int f=fat[u];  fat[u]=Fat(fat[u]);  (dis[u]+=dis[f])%=m;  return fat[u];}inline void Merge(int x,int y,int w){  int fx=Fat(x),fy=Fat(y);  if (fx==fy){    int l=(dis[x]+dis[y])%m;    g[fx]=__gcd(__gcd(g[fx],2*w),w+l);  }else{    fat[fx]=fy; dis[fx]=((ll)w+m-dis[x]+m-dis[y])%m;    g[fy]=__gcd(__gcd(g[fy],g[fx]),2*dis[fx]);  }}int main(){  int order,u,v,x,b,c,w;  read(n); read(m); read(Q);  for (int i=1;i<=n;i++) fat[i]=i;  while (Q--){    read(order); read(u); read(v);    if (order==1){      read(w); Merge(u,v,w);    }else{      read(x); read(b); read(c);      ll ans=0;      if (Fat(u)==Fat(v)){    int L=(dis[u]+dis[v])%m;    int g=__gcd(::g[Fat(u)],m);    int k=calc(b%g,((L-x)%g+g)%g,g);    if (k!=-1 && k<c){      int t=g/__gcd(g,b);      ans=(c-1-k)/t+1;    }      }      printf("%lld\n",ans);    }  }  return 0;}
阅读全文
0 0
原创粉丝点击