zoukankan      html  css  js  c++  java
  • 「POI2019 R1」Przedszkole

    Sub1 :: (mle 24)

    由于图上的边就是一条条限制,所以尝试容斥。

    暴力枚举,先选定任意条边,钦定这些边的两端点是同一种颜色,其他的颜色任意,设这些边相关的总点数为 (r) ,那么方案数为 ((n - r) ^ k) ,容斥系数就是 ((-1) ^ {[选定边数是奇数]}) ,可以用并查集维护。

    但是有多次询问,所以直接暴力是不行的。

    发现 ((n - r) ^ k) 的个数只有 (n) 个,所以先算出所有 ((n - r) ^ k) 的容斥系数就可以了。

    时间复杂度 (mathcal O (m imes 2 ^ m + zmlog n))

    Sub2 :: (nle 15)

    (n) 很小,考虑状压 DP ,传统的一个一个加点的 DP 在这里有一个很大的问题,就是无法知道所有点到底是什么颜色的。

    然后考虑一个可以不用知道原来颜色的状态,所以考虑一个每次填入一块相同颜色的 DP

    然后又由于 (n) 很小,所以一共只需要填上 (n) 次,最后方案数乘上一个组合数即可,这样又和 (k) 无关了。

    (f(i, S)) 表示已经填入了前 (i) 种颜色,填上这些颜色的点的所有点的点集为 (S) ,保证每种颜色都存在的方案数。

    那么转移为:

    [f(i, S) leftarrow sum_{Tsubset S} f(i - 1, S oplus T) imes [T 是独立集] ]

    点集是否为独立集可以 (mathcal O (n2^n)) 处理。

    时间复杂度 (mathcal O (n3^n + zn^2))

    Sub3 :: 图由多个环构成

    观察下图:

    image

    对于被划到外面的这个点的颜色方案数要么是 (k - 1) 要么是 (k - 2)

    取决于相邻两边的点是否同色。

    考虑同色的情况,把这两个点合起来变成一个点,那么就是一个长为 (n - 2) 的合法环。

    对于异色的情况,直接把两个点接上,那么就是一个长为 (n - 1) 的合法环。

    那么设长为 (n) 的合法环的方案数为 (f(n)) ,那么有递推式:

    [f(n) = (k - 2) imes f(n - 1) + (k - 1) imes f(n - 2) ]

    可以直接矩阵乘法,但是环的个数一共为 (n)

    可以发现这里有一个自然根号,对于大于 (sqrt n) 的环,最多只有 (sqrt n) 个,所以所有不同的环的总个数是 (mathcal O (sqrt n)) 级别的。

    所以就做完了,时间复杂度 (mathcal O (n + m + zsqrt nlog n))

    const int Mod = 1e9 + 7;
    namespace Modint {
    	struct Mint {
    		int res;
    		Mint() {}
    		Mint(int _r) : res(_r) {}
    		inline friend Mint operator + (const Mint& A, const Mint& B) {
    			return Mint((A.res + B.res >= Mod) ? (A.res + B.res - Mod) : (A.res + B.res));
    		}
    		inline friend Mint operator - (const Mint& A, const Mint& B) {return A + Mint(Mod - B.res); }
    		inline friend Mint operator * (const Mint& A, const Mint& B) {return Mint(1ll * A.res * B.res % Mod); }
    		inline friend Mint& operator += (Mint& A, const Mint& B) {return A = A + B; }
    		inline friend Mint& operator -= (Mint& A, const Mint& B) {return A = A - B; }
    		inline friend Mint& operator *= (Mint& A, const Mint& B) {return A = A * B; }
    		inline friend Mint q_pow(Mint p, int k = Mod - 2) {
    			Mint res(1);
    			for (; k; k >>= 1, p *= p) (k & 1) && (res *= p, 0);
    			return res;
    		}
    	} ;
    }
    using Modint :: Mint;
    typedef long long i64;
    typedef double f64;
    typedef unsigned long long u64;
    typedef pair<i64, i64> pii;
    typedef pair<int, u64> piu;
    const int N = 1e5 + 5;
    const i64 INF = 1e18;
    inline void init() {}
    int n, m, z;
    namespace SUB1 {
    	const int M = 30;
    	Mint cof[N]; int fa[N], u[M], v[M], lim;
    	int fnd(int u) {
    		return fa[u] == u ? u : fnd(fa[u]);
    	}
    	void dfs(int dep, int rem, int num) {
    		if (dep == m) {
    			if (num & 1) cof[rem] -= Mint(1);
    			else cof[rem] += Mint(1);
    			lim = min(lim, rem);
    			return ;
    		}
    		dfs(dep + 1, rem, num);
    		int Tu = fnd(u[dep]), Tv = fnd(v[dep]);
    		fa[Tv] = Tu;
    		if (Tu != Tv) dfs(dep + 1, rem - 1, num + 1);
    		else dfs(dep + 1, rem, num + 1);
    		fa[Tv] = Tv;
    	}
    	inline void solve() {
    		rep (i, 0, m) Rdn(u[i], v[i]); lim = n;
    		forn (i, 1, n) fa[i] = i;
    		dfs(0, n, 0);
    		while (z--) {
    			int k; Rdn(k);
    			Mint res(0);
    			forn (i, lim, n) res += cof[i] * q_pow(Mint(k), i);
    			Wtn(res.res, '
    ');
    		}
    	}
    }
    namespace SUB2 {
    	const int M = 20;
    	Mint f[16][1 << 15];
    	int e[16]; bool g[1 << 15]; 
    	inline Mint C(int k, int r) {
    		if (k < 0 || r < 0 || k - r < 0) return Mint(0);
    		Mint res(1);
    		forn (i, 2, r) res *= q_pow(Mint(i));
    		forn (i, k - r + 1, k) res *= Mint(i);
    		return res;
    	}
    	inline void solve() {
    		forn (i, 1, m) {
    			int u, v;
    			Rdn(u, v); --u, --v;
    			e[u] |= 1 << v;
    			e[v] |= 1 << u;
    		}
    		rep (S, 0, 1 << n) {
    			g[S] = 1;
    			rep (i, 0, n) if (S >> i & 1) if (S & e[i]) {g[S] = 0; break ;}
    		}
    		f[0][0] = Mint(1);
    		forn (i, 1, n) rep (S, 0, 1 << n) for (int T = S; T; T = S & (T - 1))
    			if (g[T]) f[i][S] += f[i - 1][S ^ T];
    		while (z--) {
    			int k; Rdn(k);
    			Mint res(0);
    			forn (i, 1, n) res += C(k, i) * f[i][(1 << n) - 1];
    			Wtn(res.res, '
    ');
    		} 
    	}
    }
    namespace SUB3 {
    	struct Mat {
    		Mint a[2][2];
    		Mat() {}
    		Mat(Mint _a11, Mint _a12, Mint _a21, Mint _a22)  {
    			a[0][0] = (_a11), a[0][1] = (_a12), a[1][0] = (_a21), a[1][1] = (_a22);
    		}
    		inline void init(bool I) {
    			memset(a, 0, sizeof a);
    			if (I) a[0][0] = a[1][1] = Mint(1);
    		}
    		inline friend Mat operator * (const Mat& A, const Mat& B) {
    			return Mat(
    				A.a[0][0] * B.a[0][0] + A.a[0][1] * B.a[1][0],
    				A.a[0][0] * B.a[0][1] + A.a[0][1] * B.a[1][1],
    				A.a[1][0] * B.a[0][0] + A.a[1][1] * B.a[1][0],
    				A.a[1][0] * B.a[0][1] + A.a[1][1] * B.a[1][1]
    			) ;
    		}
    	};
    	bool vis[N]; vector<int> T[N];
    	int dfs(int u, int lst) {
    		if (vis[u]) return 0; vis[u] = 1;
    		if (T[u][0] != lst) return dfs(T[u][0], u) + 1;
    		else return dfs(T[u][1], u) + 1;
    	}
    	int siz[N], tot, rft[N], ton[N];
    	inline void solve() {
    		forn (i, 1, m) {
    			int u, v; Rdn(u, v);
    			T[u].push_back(v), T[v].push_back(u);
    		}
    		forn (i, 1, n) if (!vis[i]) siz[++tot] = dfs(i, i), rft[tot] = siz[tot];
    		sort (rft + 1, rft + tot + 1);
    		int Rn = unique(rft + 1, rft + tot + 1) - rft - 1;
    		forn (i, 1, tot) siz[i] = lower_bound(rft + 1, rft + Rn + 1, siz[i]) - rft, ton[siz[i]] ++ ;
    		while (z--) {
    			int k; Rdn(k); Mint res(1);
    			if (k <= 2) {Wtn("0
    "); continue ; }
    			k %= Mod;
    			Mat unit = Mat(Mint(k - 2), Mint(1), Mint(k - 1), Mint(0));
    			forn (i, 1, Rn) {
    				Mat trans(Mint(1), Mint(0), Mint(0), Mint(1)), lft = unit, F(Mint(k) * Mint(k - 1) * Mint(k - 2), Mint(k) * Mint(k - 1), Mint(0), Mint(0));
    				for (int o = rft[i] - 3; o; o >>= 1, lft = lft * lft) (o & 1) && (trans = trans * lft, 0) ;
    				F = F * trans;
    				res *= q_pow(F.a[0][0], ton[i]);
    			}
    			Wtn(res.res, '
    ');
    		}
    	}
    }```
  • 相关阅读:
    markdown with vim
    递归
    类 sizeof
    cppcheck工具
    c++ explicit的含义和用法
    pca主成分分析
    string的使用
    linux的shell进化简史
    adb shell 无法启动 (insufficient permissions for device)
    c++ 四种转换的意思
  • 原文地址:https://www.cnblogs.com/Ax-Dea/p/15517618.html
Copyright © 2011-2022 走看看