列表

详情


NC13334. 神秘代号

描述

有一个古老的帝国,这个帝国有 n 个城邦,这些城邦由恰好 n 条道路连结(每条路连结两个不同的城邦,保证任意两条道路连结的城邦组不同,即没有重边),所有城邦保证连通。
每个城邦有一个神秘的代号 x_i ,每个 x_i 都是一个 [0,p-1] 范围内的非负整数,其中 p 为一个已知的质数。
由于年代过于久远,这些 x_i 已经不为人知了,但是作为一个历史爱好者,你希望考证一下这些 x_i 的值。
幸运的是,你找到了一些线索,对于每条道路你都得到了一个方程,这个方程的形式为:设这条道路连结的两个城邦为 u , v ,以及有三个参数 a , b , c,那么有 a*x_u + b*x_v = c (mod p),即这是一个在模质数 p 域下的方程。
现在你需要根据这些线索来求出一组满足条件的 x_i ,数据保证有解且解唯一。

输入描述

第一行两个正整数 n , p ( 3 ≤ n ≤ 10^5 , 3 ≤ p ≤ 10^9 )。 接下来 n 行,每行五个整数 u , v , a , b , c 描述一条道路及其参数 ( 1 ≤ u,v ≤ n , 1 ≤ a,b < p , 0 ≤ c < p )。

输出描述

输出 n 行,依次为 x_i (0 ≤ x_i < p)。

示例1

输入:

6 5
1 4 3 1 0
4 3 1 3 2
4 2 1 3 4
2 6 1 1 2
3 5 1 2 3
2 3 3 4 0

输出:

0
3
4
0
2
4

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 178ms, 内存消耗: 12480K, 提交时间: 2019-07-27 10:20:10

#include <bits/stdc++.h>
#define DEBUG
#define debug1(x) std::cout << #x " = " << (x) << std::endl
#define debug2(x, y) std::cout << #x " = " << (x) << " ," #y " = " << (y) << std::endl
#define disp(arry, fr, to) \
    { \
        std::cout << #arry " : "; \
        for(int _i = fr; _i < to; _i++) std::cout << arry[_i] << " "; \
        std::cout << std::endl; \
    }

using namespace std;

typedef long long ll;
const int MAXV=1e5+5,MAXE=MAXV<<1;
int v,mode,dp[MAXV][2]; // 从根节点开始dfs,表示这个点等于dp[i][0]+dp[i][1]*root(mod p)

ll inv(ll x)
{
    ll ans=1;
    int up=mode-2;
    while(up)
    {
        if(up&1) ans=ans*x%mode;
        x=x*x%mode;
        up>>=1;
    }
    return ans;
}

namespace G
{
    struct Edge
    {
        int to, last, a,b,c;
        void set(int _to, int _last,int _a,int _b,int _c) { to = _to, last = _last,a=_a,b=_b,c=_c; }
    } es[MAXE];

    int top, head[MAXV],uset[MAXV];

    int get_fa(int x)
    {
        if(uset[x]==x) return x;
        return uset[x]=get_fa(uset[x]);
    }

    void init()
    {
        top = 0, memset(head, -1, sizeof(head));
        for(int i=0;i<v;++i) uset[i]=i;
    }

    bool add(int fr, int to,int a,int b,int c)
    {
        int x=get_fa(fr),y=get_fa(to);
        if(x==y) return 1;
        es[top].set(to, head[fr],a,b,c);
        head[fr] = top++;
        es[top].set(fr,head[to],b,a,c);
        head[to]=top++;
        uset[x]=y;
        return 0;
    }

    void dfs(int fr,int fa)
    {
        ll tmp;
        for(int i=head[fr],to;~i;i=es[i].last)
        {
            to=es[i].to;
            if(to==fa) continue;
            tmp=inv(es[i].b);
            dp[to][0]=tmp*((es[i].c-1ll*es[i].a*dp[fr][0])%mode)%mode;
            if(dp[to][0]<0) (dp[to][0]+=mode)%=mode;
            dp[to][1]=mode-tmp*es[i].a%mode*dp[fr][1]%mode;
            dfs(to,fr);
        }
        // debug1(fr);
        // debug2(dp[fr][0],dp[fr][1]);
    }
}

int main()
{
    scanf("%d %d",&v,&mode);
    int p1,p2;
    ll k1,k2,k3;
    G::init();
    for(int i=1,fr,to,a,b,c;i<=v;++i) 
    {
        scanf("%d %d %d %d %d",&fr,&to,&a,&b,&c);
        if(G::add(fr,to,a,b,c)) p1=fr,p2=to,k1=a,k2=b,k3=c;
    }
    // debug2(p1,p2);
    dp[1][0]=0,dp[1][1]=1;
    G::dfs(1,-1);
    ll x=(k1*dp[p1][1]+k2*dp[p2][1])%mode,y=(k3-k1*dp[p1][0]-k2*dp[p2][0])%mode;
    if(y<0) (y+=mode)%=mode;
    ll ans=y*inv(x)%mode;
    for(int i=1;i<=v;++i)
        printf("%lld\n",(dp[i][0]+dp[i][1]*ans)%mode);
    return 0;
}

C++14(g++5.4) 解法, 执行用时: 169ms, 内存消耗: 17740K, 提交时间: 2020-05-20 14:48:35

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef pair<LL, LL> pll;

const int maxn = 100000 + 50;

struct Edge
{
    LL to, next, a, b, c;
} edge[maxn << 1];

LL n, mod, X;
LL tot, head[maxn];
pll val[maxn];

void AddEdge(LL u, LL v, LL a, LL b, LL c)
{
    edge[tot] = (Edge){v, head[u], a, b, c};
    head[u] = tot++;
}

LL FastPow(LL a, LL n)
{
    LL ans = 1, base = a;
    while (n)
    {
        if (n & 1)
            (ans *= base) %= mod;
        (base *= base) %= mod;
        n >>= 1;
    }
    return ans;
}

LL GetInv(LL x)
{
    return FastPow(x, mod - 2);
}

LL Cal(pll a, pll b)
{
    LL aa = (a.first - b.first + mod) % mod;
    LL bn = GetInv((b.second - a.second + mod) % mod);
    return (aa * bn) % mod;
}

void dfs(LL u, LL pre)
{
    for (LL i = head[u]; i; i = edge[i].next)
    {
        LL v = edge[i].to;
        if (v == pre)
            continue;
        LL a = edge[i].a, b = edge[i].b, c = edge[i].c;
        LL bn = GetInv(b);
        LL nx = bn * ((c - (a * val[u].first % mod) + mod) % mod) % mod;
        LL ny = bn * (mod - a * val[u].second % mod) % mod;
        pll np = make_pair(nx, ny);
        if (val[v].first < 0)
        {
            val[v] = np;
            dfs(v, u);
        }
        else
            X = Cal(val[v], np);
    }
}

LL res[maxn];

int main()
{
    scanf("%lld%lld", &n, &mod);
    tot = 1;
    LL u, v, a, b, c;
    for (LL i = 1; i <= n; ++i)
    {
        scanf("%lld%lld%lld%lld%lld", &u, &v, &a, &b, &c);
        AddEdge(u, v, a, b, c);
        AddEdge(v, u, b, a, c);
    }
    val[1] = make_pair(0, 1);
    for (LL i = 2; i <= n; ++i)
        val[i] = make_pair(-1, -1);
    dfs(1, 0);
    for (LL i = 1; i <= n; ++i)
        res[i] = (val[i].first + val[i].second * X % mod) % mod;
    for (LL i = 1; i <= n; ++i)
        printf("%lld\n", res[i]);
    return 0;
}

上一题