1. 程式人生 > >[UOJ#348][WC2018]州區劃分(狀壓dp+FMT)

[UOJ#348][WC2018]州區劃分(狀壓dp+FMT)

Address

洛谷P4221
BZOJ5153
UOJ#348
LOJ#2340

Solution

有一個顯然的 dp 方案:
f [ S ] f[S] 表示選出的城市集合為 S

S 的滿意度之和。
s u m [ S ] sum[S]
表示城市集合 S S 的人口之和。
g [ S ] g[S]
表示:
[ S ] × s u m [ S ] p [子圖S不存在歐拉回路]\times sum[S]^p
轉移顯然:
f [ S ] = 1 s u m [ S ] p T S f [ T ] g [ S T ] f[S]=\frac1{sum[S]^p}\sum_{T\subsetneq S}f[T]g[S-T]
複雜度 O ( 3 n ) O(3^n) ,難以通過 n = 21 n=21 的資料。
考慮到這是子集卷積的形式,不妨把 f f 按照 S S 集合大小分類:
f [ i ] [ S ] f[i][S] 表示:
{ f [ S ] S = i 0 ELSE \begin{cases}f[S]&|S|=i\\0&\text{ELSE}\end{cases}
那從小到大列舉 i i ,再列舉一個 0 j < i 0\le j<i ,那麼 f [ i ] f[i] 就能從 f [ j ] f[j] g [ i j ] g[i-j] 轉移。
如果已經求得了 f [ 0... i 1 ] f[0...i-1] 的快速莫比烏斯變換 f [ 0 ] , f [ 1 ] , . . . , f [ i 1 ] f[0]',f[1]',...,f[i-1]'
以及 g g 的 FMT g g' ,
那麼就可以直接計算 f [ i ] [ S ] + = f [ j ] [ S ] × g [ i j ] [ S ] f[i]'[S]+=f[j]'[S]\times g[i-j]'[S]
反演回去之後將每個 f [ i ] [ S ] f[i][S] 除以 s u m [ S ] p sum[S]^p
注意需要將 S i |S|\ne i f [ i ] [ S ] f[i][S] 清零。
複雜度 O ( 2 n × n 2 ) O(2^n\times n^2)

Code

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define For(i, a, b) for (i = a; i <= b; i++)
#define Rof(i, a, b) for (i = a; i >= b; i--)
#define Subset(k, i) for (k = i; k; k = (k - 1) & i)
using namespace std;

inline int read()
{
	int res = 0; bool bo = 0; char c;
	while (((c = getchar()) < '0' || c > '9') && c != '-');
	if (c == '-') bo = 1; else res = c - 48;
	while ((c = getchar()) >= '0' && c <= '9')
		res = (res << 3) + (res << 1) + (c - 48);
	return bo ? ~res + 1 : res;
}

const int N = 25, C = (1 << 21) + 5, MOD = 998244353;

int qpow(int a, int b)
{
	int res = 1;
	while (b)
	{
		if (b & 1) res = 1ll * res * a % MOD;
		a = 1ll * a * a % MOD;
		b >>= 1;
	}
	return res;
}

int n, m, p, Cm, w[N], cnt[N], f[N][C], sum[C], inv[C], ans, eul[N][C],
sze[C], fa[N];
bool gr[N][N], cir[C];

void FWT(int n, int *a, int op)
{
	int i, j;
	For (i, 1, n) For (j, 0, (1 << n) - 1)
		if (!((j >> i - 1) & 1))
			a[j | (1 << i - 1)] = (a[j | (1 << i - 1)]
				+ (op == 1 ? a[j] : MOD - a[j])) % MOD;
}

int fd(int x)
{
	if (fa[x] != x) fa[x] = fd(fa[x]);
	return fa[x];
}

void mg(int x, int y)
{
	int ix = fd(x), iy = fd(y);
	if (ix != iy) fa[iy] = ix;
}

int main()
{
	int i, j, S, x, y;
	n = read(); m = read(); p = read();
	Cm = (1 << n) - 1;
	For (i, 1, m) x = read(), y = read(),
		gr[x][y] = gr[y][x] = 1;
	For (i, 1, n) w[i] = read();
	For (S, 1, Cm)
	{
		For (i, 1, n) cnt[i] = 0, fa[i] = i; int xp = 0;
		For (i, 1, n) if ((S >> i - 1) & 1)
		{
			sum[S] += w[i]; sze[S]++; xp = i;
			For (j, i + 1, n) if (((S >> j - 1) & 1) && gr[i][j])
				cnt[i]++, cnt[j]++, mg(i, j);
		}
		sum[S] = qpow(sum[S], p);
		inv[S] = qpow(sum[S], MOD - 
            
           

相關推薦

[UOJ#348][WC2018]州區劃分dp+FMT

Address 洛谷P4221 BZOJ5153 UOJ#348 LOJ#2340 Solution 有一個顯然的 dp 方案: f [

Luogu4221 WC2018州區劃分dp+FWT

+= 就是 online lse etc \n ring 不用 degree   合法條件為所有劃分出的子圖均不存在歐拉回路或不連通,也即至少存在一個度數為奇數的點或不連通。顯然可以對每個點集預處理是否合法,然後就不用管這個奇怪的條件了。   考慮狀壓dp。設f[S]為S集

[WC2018]州區劃分 - FWT - dp

……直接記bitcount然後FWT即可。 // luogu-judger-enable-o2 #include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std;ty

WC2018州區劃分-FWT+DP

Description 連結 Solution 首先我們可以輕鬆預處理出滿足條件的點集。 設 f s

【題解】洛谷P3959 [NOIP2017TG] 寶藏DP+DFS

洛谷P3959:https://www.luogu.org/problemnew/show/P3959 前言 NOIP2017時還很弱(現在也很弱 看出來是DP 但是並不會狀壓DP 現在看來思路並不複雜 只是存狀態有點難想到 思路 因為n最大為12 所以可以想到是狀壓  

洛谷3959 寶藏DP bczd

傳送門 【題目分析】 看看這隻有12的資料規模,那麼狀壓沒跑了。 轉移也很好想,列舉起點,更新dp值。。。。。。然後就被hack了。。。。。 hack資料:6 6 1 2 100 2 3 1 2 4 10 3 4 10 3 5 100 4 6 10000 所以這就是所謂的錯誤做法

【bzoj 1076】[SCOI2008]獎勵關dp+概率

1076: [SCOI2008]獎勵關 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1817  Solved: 994 [Submit][Stat

WC2018州區劃分FWT,動態規劃

cap %d void turn href style int () bre 【WC2018】州區劃分(FWT,動態規劃) 題面 UOJ 洛谷 題解 首先有一個暴力做法(就有\(50\)分了) 先\(O(2^nn^2)\)預處理出每個子集是否合法,然後設\(f[S]\)表示

uoj#37. 【清華集訓2014】主旋律dp+容斥

傳送門 第一眼容斥,然後我就死活容不出來了…… 記\(f_i\)為點集\(i\)中的點強聯通的方案數,那麼就是總的方案數減去使\(i\)不連通的方案數 如果\(i\)不連通的話,我們可以列舉縮點之後拓撲序最小(也就是入度為\(0\))的強連通分量,然而這種強聯通分量可能不止一個,需要容斥,不難發現這裡的

SRM709 div1 Xscoregamedp

壓縮 out find 初始 reg max algo pan 是我 題目大意: 給定一個序列a,包含n個數(n<=15),每個數的大小小於等於50 初始時x = 0,讓你每次選a中的一個數y,使得x = x + x^y 問如何安排選擇的次序,使得最終結果最大。

【NOIP2016提高組】憤怒的小鳥寬搜

數組保存 結果 4.0 2.0 pac 之前 第一個 ... 預處理 題目描述 Kiana最近沈迷於一款神奇的遊戲無法自拔。 簡單來說,這款遊戲是在一個平面上進行的。 有一架彈弓位於(0,0)處,每次Kiana可以用它向第一象限發射一只紅色的小鳥,小鳥們的飛行軌跡均為形如的

lightoj 1057 - Collecting Golddp

define har ring volume www lightoj cst con continue 題目鏈接:http://www.lightoj.com/volume_showproblem.php?problem=1057 題解:看似有點下記憶話搜索但是由於

dpABC 067 F : Mole and Abandoned Mine

技術分享 cts using sub src oops bit live set Mole decided to live in an abandoned mine. The structure of the mine is represented by a simple

dpUVA - 1252 Twenty Questions

ace code return uva typedef clu http 狀壓 .net 題目地址 讀入二進制數及轉換的方法。 e.g. bitset<16> x;   cin>>x;   cout<<x.to_ulong()<&l

POJ 2288 Islands and Bridgesdp

pen clas tdi pac pre 初始 路徑 nds queue http://poj.org/problem?id=2288 題意: 有n個島嶼,每個島嶼有一個權值V,一條哈密頓路徑C1,C2,...Cn的值為3部分之和: 第1部分,將路徑中每個島嶼的權值累

dpNOI 2001POJ 1185 炮兵陣地

上下 數據 enter 能夠 sam src max spa 參加 司令部的將軍們打算在N*M的網格地圖上部署他們的炮兵部隊。一個N*M的地圖由N行M列組成,地圖的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示),如下圖。在每一格平原地形上最多可以布置一支炮

dpHDU 4778 Gems Fight!

ont magic fig urn turn sid several desc ant Gems Fight! Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 327680/327680 K (Java/O

[luoguP1896] [SCOI2005]互不侵犯KingDP

放置 puts turn true i++ bsp pri += light 傳送門 先預處理出來一行中放置國王的所有情況和每種情況所用的國王個數。 f[i][j][k]表示前i行放j個國王且最後一行的狀態為k的方案數 狀壓DP即可 #include &l

[luoguP2622] 關燈問題II最短路

ostream 狀壓 狀壓dp amp queue tps printf size fin 傳送門 本以為是狀壓DP,但是有後效性。 所以寫一手狀壓spfa #include <queue> #include <cstdio>

[luoguP2704] 炮兵陣地DP

pro 狀態 blank show char %d har void href 傳送門 可以事先把每一行的所有狀態處理出來,發現每一行的狀態數最多不超過60個 f[i][j][k]表示前i行,第i行為狀態j,第i-1行為狀態k的最優解 #include