HDU - 6064 RXD and numbers

题意:

求有多少序列 A 1 , A 2 , ⋯   , A n A_1, A_2, \cdots, A_n A1,A2,,An 满足以下条件:

  • 1 ≤ A i ≤ m 1 \leq A_i \leq m 1Aim
  • A 1 = A n = 1 A_1 = A_n = 1 A1=An=1
  • ∀   1 ≤ x ≤ m ,   ∃   p ,   A p = x \forall~1 \leq x \leq m, ~\exists ~p,~A_p = x  1xm,  p, Ap=x
  • 1 ≤ i < n 1 \leq i \lt n 1i<n,使得 A i = x , A i + 1 = y A_i = x, A_{i + 1} = y Ai=x,Ai+1=y 成立的 i i i D x , y D_{x, y} Dx,y 个。

答案模上 998244353 998244353 998244353 ( n > 2 , 1 ≤ m ≤ 400 , 0 ≤ D x , y < 500 ) (n \gt 2,1 \leq m \leq 400, 0 \leq D_{x, y} \lt 500) (n>2,1m400,0Dx,y<500)

链接:

https://vjudge.net/problem/HDU-6064

解题思路:

抽象出 m m m 个顶点,已知 x → y x \rightarrow y xy D x , y D_{x, y} Dx,y 条边,问从 1 1 1 号顶点出发的欧拉回路有几条。首先判定图是否为欧拉图,即连通且每个顶点入度等于出度,若不为欧拉图则答案为 0 0 0。否则,为欧拉回路计数,用 B E S T BEST BEST 定理求解。注意这里欧拉回路定起点,则在 B E S T BEST BEST 定理基础上再乘上 i n [ 1 ] in[1] in[1],并且重边在原问题序列 A A A 中体现为相同的序列,需要去重,即除以 ∏ i = 1 m ∏ j = 1 m D i , j ! \prod\limits_{i = 1}^{m}\prod\limits_{j = 1}^{m} D_{i, j}! i=1mj=1mDi,j!

参考代码:
#include<bits/stdc++.h>
 
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define sz(a) ((int)a.size())
#define pb push_back
#define lson (rt << 1)
#define rson (rt << 1 | 1)
#define gmid (l + r >> 1)
const int maxn = 5e2 + 5;
const int inf = 0x3f3f3f3f;
const int mod = 998244353;

struct MatTree{

    ll K[maxn][maxn]; int n;
    void init(int nn){
    
        n = nn;
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= n; ++j) K[i][j] = 0;
    }
    void add(int u, int v, int w = 1, int t = 1){

        t ? (K[u][u] += w) %= mod : (K[v][v] += w) %= mod;
        (K[u][v] -= w) %= mod;
    }
    ll det(){

        ll ret = 1;
        for(int i = 1; i <= n; ++i){

            for(int j = i + 1; j <= n; ++j){

                while(K[j][i]){

                    ll t = K[i][i] / K[j][i];
                    for(int k = i; k <= n; ++k){

                        K[i][k] -= K[j][k] * t;
                        K[i][k] = (K[i][k] % mod + mod) % mod;
                        swap(K[i][k], K[j][k]);
                    }
                    ret = -ret;
                }
            }
            if(!K[i][i]) return 0;
            ret = ret * K[i][i] % mod;
        }
        return (ret + mod) % mod;
    }
    ll solve(int rt){

        for(int i = 1; i <= n; ++i) K[rt][i] = K[i][rt] = 0;
        K[rt][rt] = 1;
        return det();
    }
} mattr;

const int maxm = maxn * maxn;
int fac[maxm], inv[maxm], finv[maxm];
int a[maxn][maxn], in[maxn], out[maxn];
int m;

int main(){
 
    ios::sync_with_stdio(0); cin.tie(0);
    fac[0] = inv[0] = finv[0] = 1;
    for(int i = 1; i < maxm; ++i){

        fac[i] = fac[i - 1] * 1ll * i % mod;
        inv[i] = i > 1 ? (mod - mod / i) * 1ll * inv[mod % i] % mod : 1;
        finv[i] = finv[i - 1] * 1ll * inv[i] % mod;
    }
    int cas = 0;
    while(cin >> m){

        mattr.init(m);
        for(int i = 1; i <= m; ++i){

            in[i] = out[i] = 0;
        }
        for(int i = 1; i <= m; ++i){

            for(int j = 1; j <= m; ++j){

                cin >> a[i][j];
                mattr.add(i, j, a[i][j]);
                in[j] += a[i][j], out[i] += a[i][j];
            }
        }
        int flg = 1;
        for(int i = 1; i <= m; ++i){

            if(!in[i] || in[i] != out[i]) { flg = 0; break; }
        }
        cout << "Case #" << ++cas << ": ";
        if(!flg){

            cout << "0\n";
            continue;
        }
        int ret = mattr.solve(1);
        for(int i = 1; i <= m; ++i) ret = ret * 1ll * fac[in[i] - 1] % mod;
        ret = ret * 1ll * in[1] % mod;
        for(int i = 1; i <= m; ++i){

            for(int j = 1; j <= m; ++j) ret = ret * 1ll * finv[a[i][j]] % mod;
        }
        cout << ret << "\n";
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值