我是靠谱客的博主 无情悟空,最近开发中收集的这篇文章主要介绍LOJ2540 「PKUWC2018」随机算法(状态压缩),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

传送门:https://loj.ac/problem/2540


s o l u t i o n solution solution:
直接状压 d p dp dp
f s , i f_{s,i} fs,i表示独立集的状态为 s s s,考虑到排列的第 i i i
枚举下一位转移

考虑下一位可以填什么
考虑现在可以加入独立集的点,之前肯定没考虑过,直接转移到 f s ∪ x , i + 1 f_{s∪{x},i+1} fsx,i+1
不可以加入独立集的点我们并不关心具体是哪个,只关心个数,直接转移到 f s , i + 1 f_{s,i+1} fs,i+1
复杂度 O ( 2 n ∗ n 2 ) O(2^n*n^2) O(2nn2)
把跑不到的状态直接剪掉就能卡过去了-.-

另有多记录一个东西后压掉一维的 O ( 2 n ∗ n ) O(2^n*n) O(2nn)做法

代码:

#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = j;i <= k;++i)
#define repp(i,j,k) for(int i = j;i >= k;--i)
#define rept(i,x) for(int i = linkk[x];i;i = e[i].n)
#define P pair<int,int>
#define Pil pair<int,ll>
#define Pli pair<ll,int>
#define Pll pair<ll,ll>
#define pb push_back 
#define pc putchar
#define mp make_pair
#define file(k) memset(k,0,sizeof(k))
#define ll long long
int rd()
{
    int sum = 0;char c = getchar();bool flag = true;
    while(c < '0' || c > '9') {if(c == '-') flag = false;c = getchar();}
    while(c >= '0' && c <= '9') sum = sum * 10 + c - 48,c = getchar();
    if(flag) return sum;
    else return -sum;
}
const int p = 998244353;
int n,m,ms;
int ans,mx;
int bin[25],fail[1100000],num[1100000],v[1100000],trans[1100000];
int f[1100000][20];
bool flag[1100000];
int Pow(int a,int x)
{
	int now = 1;
	while(x)
	{
		if(x&1) now = 1ll*now*a%p;
		a = 1ll*a*a%p;
		x >>= 1;
	}
	return now;
}
void init()
{
	n = rd();m = rd();
	ms = (1<<n)-1;
	rep(i,0,n) fail[bin[i-1]] = bin[i-1];
	rep(i,1,m)
	{
		int x = rd(),y = rd();
		fail[bin[x-1]] |= bin[y-1];
		fail[bin[y-1]] |= bin[x-1];
	}
	flag[0] = true;
	rep(s,0,ms) if(flag[s])
	    rep(j,1,n) if((!(s>>j-1&1)) && (!(bin[j-1]&fail[s])))
	    {
	    	flag[s|bin[j-1]] = true;
	    	num[s|bin[j-1]] = num[s] + 1;
	    	fail[s|bin[j-1]] = fail[s]|fail[bin[j-1]];
	    	mx = max(mx,num[s|bin[j-1]]);
	    }
	rep(s,0,ms)
	{
		int to = (~(fail[s]))&ms;
		trans[s] = to;
		while(to) to -= to&-to,v[s]++;
	}
}
int inv[30];
void Dp()
{
	f[0][0] = 1;
	int ans = 0;
	rep(i,1,25) inv[i] = Pow(i,p-2);
	rep(s,0,ms) rep(i,0,n)
	    if(f[s][i])
	    {
	    	if(num[s] == mx && i == n) (ans += f[s][i])%=p;
	    	f[s][i] = 1ll*f[s][i]*inv[n-i]%p;
	    	for(int to = trans[s];to;to -= to&-to)
	    	{
	    		int k = to&-to;
	    		(f[s|k][i+1] += f[s][i])%=p;
	    	}
	    	(f[s][i+1] += (1ll*f[s][i]*(n-i-v[s])%p))%=p;
	    }
    printf("%dn",ans);
}
int main()
{
	bin[0] = 1;rep(i,1,21) bin[i] = bin[i-1]<<1;
	init();
	Dp();
    return 0;
}

最后

以上就是无情悟空为你收集整理的LOJ2540 「PKUWC2018」随机算法(状态压缩)的全部内容,希望文章能够帮你解决LOJ2540 「PKUWC2018」随机算法(状态压缩)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(57)

评论列表共有 0 条评论

立即
投稿
返回
顶部