PKUWC2018 隨機演算法

2022-03-27 01:20:05 字數 1734 閱讀 6068

題目

思博狀壓寫不出是不是沒救了呀

首先我們直接狀壓當前最大獨立集的大小顯然是不對的,因為我們的答案還和我們考慮的順序有關

我們發現最大獨立集的個數好像不是很多,可能是\(o(n)\)級別的,於是我們考慮從這個方面入手

我們求出所有的最大獨立集,考慮求出有多少種考慮順序能夠恰好得到這個最大獨立集

設當前已經考慮的點的狀態為\(s\)時的方案數為\(dp_s\)

我們考慮列舉出乙個不在狀態\(s\)的點\(x\)

分兩種情況

\(x\)是最大獨立集的點,所以我們可以把這個點加入\(s\)

\(x\)不是最大獨立集的點,我們發現只有當和這個點相鄰的且屬於最大獨立集的點加入\(s\),我們才能加入\(x\),這樣\(x\)才能不被加入獨立集

於是我們這樣做就好啦,複雜度是\(o(2^nn^2)\),卡卡常數就過去啦

**

#include#include#include#include#define re register

#define ll long long

#define lb(x) ((x)&(-x))

#define max(a,b) ((a)>(b)?(a):(b))

#define min(a,b) ((a)<(b)?(a):(b))

const int maxn=(1<<20)+5;

const int mod=998244353;

inline int read()

int st[maxn][21],top[maxn];

int cnt[maxn],f[maxn],vis[22],tot,ans,inv[22];

int n,m,n,d[22],g[maxn],dp[maxn],lg[maxn];

inline int chk(int s)

return 1;

}inline void get(int s,int p)

}inline int qm(int a)

inline int calc(int s)

memset(dp,0,sizeof(dp));

dp[0]=1;

for(re int i=0;i>1]+(i&1);

for(re int x,y,i=1;i<=m;i++)

for(re int i=1;i<=n;i++) lg[1<<(i-1)]=i;

for(re int i=0;i<=n;i++) get(n^i,i);

for(re int i=1;i<=n;i++) f[i]=chk(i);

for(re int i=1;i<=n;i++) if(f[i]&&cnt[i]>cnt[ans]) ans=i;

for(re int i=1;i<=n;i++)

if(f[i]&&cnt[i]==cnt[ans])

tot=qm(tot+calc(i));

inv[1]=1;

for(re int i=2;i<=n;i++) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;

for(re int i=2;i<=n;i++) tot=(1ll*tot*inv[i])%mod;

printf("%d\n",tot);

return 0;

}

至於\(o(2^nn)\)的正解好像很神仙的樣子,大概是加入乙個點的時候把和它相連的點都加入進來,轉移的過程中還要乘上排列數,一看我就不會,於是就不寫啦

PKUWC2018 隨機演算法

題意 給定乙個圖 n 20 定義乙個求最大獨立集的隨機化演算法 產生乙個排列,依次加入,能加入就加入 求得到最大獨立集的概率 本質就是計數題 每個點有三種狀態 考慮過且在獨立集中,考慮過未在獨立集中,未考慮 本來在集合裡的點不能知道有哪些,而且不能加入的點的排列也不好確定。乙個好的方法是 把考慮過的...

pkuwc2018 隨機演算法

我們考慮用狀壓dp來解決這一道題 設 f i s 表示當前排列的前i位所構成的最大獨立集恰好為s的方案數 我們考慮用 f i s 推出 f i 1 s 的值 那麼我們有兩種擴充套件的方法,一種是在第 i 1 位,加入乙個數 j 滿足 s j 且 s j 為最大獨立集。這種情況,相當於在原本的最大獨立...

PKUWC2018 隨機演算法

我們知道,求任意圖的最大獨立集是一類np完全問題,目前還沒有準確的多項式演算法,但是有許多多項式複雜度的近似演算法。例如,小 c 常用的一種演算法是 1.對於乙個 n 個點的無向圖,先等概率隨機乙個 1 ldots n 的排列 p 1 ldots n 2.維護答案集合 s 一開始 s 為空集,之後按...