題目
思博狀壓寫不出是不是沒救了呀
首先我們直接狀壓當前最大獨立集的大小顯然是不對的,因為我們的答案還和我們考慮的順序有關
我們發現最大獨立集的個數好像不是很多,可能是\(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 為空集,之後按...