[美团 CodeM 复赛]神秘代号

xiaoxiao2021-02-28  87

题目大意

n个点n条边的联通无向图,每个点i有一个[0,p)的数xi,p是个质数。 每条边(u,v)都有一条方程形如 axu+bxvc(mod p) 保证x有解且有唯一解,求出x。

解方程

假定一个位置的值是x,然后从这个位置bfs通过边上的方程用x表示出其余每个点的值。 因为一定有环所以可以在某条边上解方程得到x。

#include<cstdio> #include<algorithm> #define fo(i,a,b) for(i=a;i<=b;i++) using namespace std; typedef long long ll; const int maxn=100000+10; int h[maxn],go[maxn*2],nxt[maxn*2],a[maxn*2],b[maxn*2],c[maxn*2]; int kk[maxn],bb[maxn],dl[maxn],d[maxn],fa[maxn]; int i,j,k,l,r,t,n,m,p,head,tail,xx,tot,now; bool czy; int qsm(int x,int y){ if (!y) return 1; int t=qsm(x,y/2); t=(ll)t*t%p; if (y%2) t=(ll)t*x%p; return t; } void add(int x,int y,int aa,int bb,int cc){ go[++tot]=y; a[tot]=aa; b[tot]=bb; c[tot]=cc; nxt[tot]=h[x]; h[x]=tot; } int main(){ //freopen("C.in","r",stdin); scanf("%d%d",&n,&p); fo(i,1,n){ scanf("%d%d%d%d%d",&j,&k,&l,&r,&t); add(j,k,l,r,t);add(k,j,r,l,t); } head=0;tail=1; dl[1]=1; d[1]=1; kk[1]=1;bb[1]=0; while (head<tail){ now=dl[++head]; t=h[now]; while (t){ if (d[go[t]]==0){ d[go[t]]=1; kk[go[t]]=(p-(ll)a[t]*qsm(b[t],p-2)%p*kk[now]%p)%p; bb[go[t]]=(ll)(c[t]-(ll)a[t]*bb[now]%p)%p*qsm(b[t],p-2)%p; dl[++tail]=go[t]; fa[go[t]]=now; } else{ k=((ll)kk[now]*a[t]%p+(ll)kk[go[t]]*b[t]%p)%p; if (k){ r=((ll)bb[now]*a[t]%p+(ll)bb[go[t]]*b[t]%p)%p; xx=(ll)(c[t]-r)%p*qsm(k,p-2)%p; } } t=nxt[t]; } } fo(i,1,n){ t=((ll)kk[i]*xx%p+bb[i])%p; (t+=p)%=p; printf("%d\n",t); } }
转载请注明原文地址: https://www.6miu.com/read-61971.html

最新回复(0)