概述
传送门: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}
fs∪x,i+1
不可以加入独立集的点我们并不关心具体是哪个,只关心个数,直接转移到
f
s
,
i
+
1
f_{s,i+1}
fs,i+1
复杂度
O
(
2
n
∗
n
2
)
O(2^n*n^2)
O(2n∗n2)
把跑不到的状态直接剪掉就能卡过去了-.-
另有多记录一个东西后压掉一维的 O ( 2 n ∗ n ) O(2^n*n) O(2n∗n)做法
代码:
#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」随机算法(状态压缩)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复