zoukankan      html  css  js  c++  java
  • UOJ #181. 【UR #12】密码锁(竞赛图+概率)

    http://uoj.ac/problem/181

    题解:

    这个需要知道竞赛图统计强联通分量的个数的思路(套路)。

    考虑竞赛图缩图之后是一条链,枚举这条链的一条边,把图分为左右两部分,之间的边是单向的就数量+1。

    这题n比较大,不能暴力(O(2^n))

    但是可以对每个特殊边的联通块做一遍,那么其它边都是(1/2)可以快速算。

    最后是若干OGF卷起来,暴力即可。

    Code:

    #include<bits/stdc++.h>
    #define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
    #define ff(i, x, y) for(int i = x, _b = y; i <  _b; i ++)
    #define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
    #define ll long long
    #define pp printf
    #define hh pp("
    ")
    using namespace std;
    
    const int mo = 998244353;
    
    ll ksm(ll x, ll y) {
    	ll s = 1;
    	for(; y; y /= 2, x = x * x % mo)
    		if(y & 1) s = s * x % mo;
    	return s;
    }
    
    const ll ni2 = ksm(2, mo - 2);
    
    const int N = 40;
    
    int n, m;
    ll x, y, z;
    
    ll aw[N * N], bw[N * N], cw[N * N];
    
    ll a[N][N];
    
    vector<int> e[N];
    #define pb push_back
    #define si size()
    
    int bz[N], d[N], d0;
    
    void dg(int x) {
    	if(bz[x]) return;
    	bz[x] = 1;
    	d[++ d0] = x;
    	ff(_y, 0, e[x].si) {
    		int y = e[x][_y];
    		dg(y);
    	}
    }
    
    ll f[N], g[N], h[N];
    
    int p[N], p0, q[N], q0;
    
    void juanji() {
    	fo(i, 0, n) h[i] = f[i], f[i] = 0;
    	fo(i, 0, n) if(h[i]) fo(j, 0, n - i) if(g[j]) {
    		f[i + j] = (f[i + j] + h[i] * g[j] % mo) % mo;
    	}
    }
    
    ll sum = 0;
    
    void dfs(int x) {
    	if(x > d0) {
    		ll s = 1;
    		fo(i, 1, p0) fo(j, 1, q0)
    			s = s * a[p[i]][q[j]] % mo;
    		s = s * bw[p0 * q0] % mo;
    		if(p0 > 0 && p0 < n) sum = (sum + s * aw[p0 * (n - p0)] % mo) % mo;
    		g[p0] = (g[p0] + s) % mo;
    		return;
    	}
    	p[++ p0] = d[x];
    	dfs(x + 1);
    	p0 --;
    	q[++ q0] = d[x];
    	dfs(x + 1);
    	q0 --;
    }
    
    int main() {
    	scanf("%d %d", &n, &m);
    	fo(i, 1, n) {
    		fo(j, i + 1, n) a[i][j] = a[j][i] = 5000;
    	}
    	aw[0] = 1; fo(i, 1, n * n) aw[i] = aw[i - 1] * 5000 % mo;
    	fo(i, 0, n * n) bw[i] = ksm(aw[i], mo - 2);
    	cw[0] = 1; fo(i, 1, n * n) cw[i] = cw[i - 1] * 10000 % mo;
    	fo(i, 1, m) {
    		scanf("%lld %lld %lld", &x, &y, &z);
    		a[x][y] = z; a[y][x] = 10000 - z;
    		e[x].pb(y); e[y].pb(x);
    	}
    	f[0] = 1;
    	fo(i, 1, n) if(!bz[i]) {
    		d0 = 0;
    		dg(i);
    		fo(j, 0, n) g[j] = 0;
    		dfs(1);
    		juanji();
    	}
    	ll ans = 0;
    	fo(i, 1, n - 1) ans = (ans + f[i] * aw[i * (n - i)] % mo * cw[n * (n - 1) / 2 - i * (n - i)]) % mo;
    	ans = (ans + cw[n * (n - 1) / 2]) % mo;
    	ans = (ans % mo + mo) % mo;
    	ans = ans * cw[n * (n - 1) / 2] % mo;
    	pp("%lld
    ", ans);
    }
    
  • 相关阅读:
    win10下VMware15运行ubuntu18.04无法和主机之间复制粘贴问题
    Redis的五种数据类型
    celery的入门使用
    Django/Flask的一些实现方法
    Python3实现简单的钉钉机器人调用
    装饰者模式
    pyhdfs安装
    使用setup.py安装python包和卸载python包的方法
    zookeeper搭建
    S3C6410裸奔之旅——RVDS2.2编译、仿真、调试过程 LED流水灯---转的
  • 原文地址:https://www.cnblogs.com/coldchair/p/12966623.html
Copyright © 2011-2022 走看看