题目
题目链接:https://www.ybtoj.com.cn/contest/114/problem/2
(nleq 100,mleq 2000,a,b<Pleq 10^{18})。
思路
上来就是一堆条件要你求值直接劝退。。。
根据条件三,可以得到对于任意一个环
[sum B(v_i,v_{i+1})C(v_i,v_{i+1})-A(v_i,v_{i+1})equiv 0pmod p
]
对于一条边 ((u,v)),记 (D(u,v)=sum B(v_i,v_{i+1})C(v_i,v_{i+1})-A(v_i,v_{i+1})),对于环上两点 (x,y),我们把环拆成 (x o y) 和 (y o x) 的路径,那么
[sum_{x o y}D(v_i,v_{i+1})+sum_{y o x}D(u_i,u_{i+1})equiv 0pmod p
]
再根据条件一
[sum_{x o y}D(v_i,v_{i+1})equivsum_{y o x}D(u_{i+1},u_i) pmod p
]
也就是任意两条 (x o y) 的路径中,(sum D) 都相等。
所以考虑做差分,记 (g_x) 表示 (1) 到 (x) 的 (sum D),那么 (D(x,y)=g_y-g_x)。
然后根据条件二可以对每一个点 (x) 列出一个方程
[sum_{(x,y)in E}frac{g_y-g_x+A(x,y)}{B(x,y)}equiv 0pmod p
]
高斯消元 (O(n^3)) 求出 (g),然后就知道 (C) 了。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
const int N=110,M=2010;
int n,m,U[M],V[M];
ll MOD,a[N][N],b[N][N],f[N][N],g[N];
bool G[N][N];
ll fmul(ll x,ll y)
{
ll z=(ld)x*y/MOD,res=x*y-z*MOD;
return (res%MOD+MOD)%MOD;
}
ll fpow(ll x,ll k)
{
ll ans=1;
for (;k;k>>=1,x=fmul(x,x)%MOD)
if (k&1) ans=fmul(ans,x)%MOD;
return ans;
}
void gauss()
{
for (int i=1;i<=n;i++)
{
for (int j=i;j<=n;j++)
if (f[j][i])
{
for (int k=1;k<=n;k++)
swap(f[i][k],f[j][k]);
swap(g[i],g[j]);
break;
}
for (int j=i+1;j<=n;j++)
if (f[j][i])
{
ll base=fmul(f[i][i],fpow(f[j][i],MOD-2))%MOD;
for (int k=1;k<=n;k++)
f[j][k]=(fmul(f[j][k],base)-f[i][k])%MOD;
g[j]=(fmul(g[j],base)-g[i])%MOD;
}
}
for (int i=n;i>=1;i--)
{
ll sum=0;
for (int j=i+1;j<=n;j++)
sum=(sum+fmul(g[j],f[i][j]))%MOD;
g[i]=fmul(g[i]-sum,fpow(f[i][i],MOD-2))%MOD;
}
}
int main()
{
freopen("graph.in","r",stdin);
freopen("graph.out","w",stdout);
scanf("%d%d",&n,&m);
scanf("%lld",&MOD);
for (int i=1,x,y;i<=m;i++)
{
scanf("%d%d",&U[i],&V[i]); x=U[i]; y=V[i];
scanf("%lld%lld",&a[x][y],&b[x][y]);
G[x][y]=G[y][x]=1;
a[y][x]=-a[x][y]; b[y][x]=b[x][y];
}
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (G[i][j])
{
ll inv=fpow(b[i][j],MOD-2);
f[i][j]=inv; f[i][i]=(f[i][i]-inv)%MOD;
g[i]=(g[i]-fmul(inv,a[i][j]))%MOD;
}
gauss();
for (int i=1;i<=m;i++)
{
int u=U[i],v=V[i];
printf("%lld
",fmul(g[v]-g[u]+a[u][v],fpow(b[u][v],MOD-2)));
}
return 0;
}