uoj
洛谷首先有乙個暴力做法(就有\(50\)分了)
先\(o(2^nn^2)\)預處理出每個子集是否合法,然後設\(f[s]\)表示當前的答案,每次列舉乙個子集進行轉移,得到方程:\(\displaystyle f[s]=(\frac)^p\sum_f[t]*(w_)^p*check[s-t]\)。
其中\(w\)表示權值和,\(check\)表示是否合法。
這樣子的複雜度是\(o(3^n)\),然後似乎可以拿\(50\)分了。
後面那個東西很像乙個卷積,然而直接\(or\)卷積的話,會算出很多我們不想要的東西。
聽說這個玩意叫做子集卷積。
要做的就是\(\sum f[t]*g[w]*[t\cup w=s,t\cap w=\phi]\)
可以用二進位制下\(1\)的個數來表示這個限制\(\sum f[t]*g[w]*[t\cup w=s,cnt(t)+cnt(w)=cnt(s)]\)。
其中\(cnt(s)\)表示\(s\)中\(1\)的個數。
然後聽說這個玩意就是乙個套路了。。。
把集合的\(1\)的個數強制作為一維狀態加上去。也就是\(f[cnt(s)][s]\)這樣子。
令\(g[cnt(s)][s]=(w_s)^p*check[s]\)。
這樣子的話只需要列舉兩者的\(1\)的個數就可以去掉位的限制,然後就只剩下兩者的交是\(s\)的限制,這個限制可以直接表示為或卷積(異或似乎也行???)。
那麼直接\(fwt\)按層處理即可。
#include#includeusing namespace std;
#define mod 998244353
#define max 25
void add(int &x,int y)
inline int read()
int fpow(int a,int b)
return s;
}int n,m,p,s,g[max],dg[max],lg[1<<21];
bool chk[1<<21];
int cc[1<<21];
int f[22][1<<21],g[22][1<<21],tmp[1<<21];
int w[max],w[1<<21],wk[1<<21],invw[1<<21];
void fwt(int *a,int opt)
chk[i]=false;int nw=0;
for(int j=0;jfor(int j=0;jfor(int j=0;jfor(int j=0;jif(cc[i]==1)chk[i]=false;
wk[i]=fpow(w[i],p);invw[i]=fpow(wk[i],mod-2);
if(chk[i])g[cc[i]][i]=wk[i];
} f[0][0]=1;fwt(f[0],1);
for(int i=1;i<=n;++i) /*
f[0]=1;
for(int i=1;if[i]=1ll*f[i]*invw[i]%mod;
}*/printf("%d\n",f[n][s-1]);
return 0;
}
WC2018 州區劃分
點此看題 設d p s dp s dp s 為選出來的點狀壓為s ss,所得到的滿意度總和,轉移 d p s 1 f s i s dp i g s i dp s frac sum dp i times g s i dp s f s 1 i s d p i g s i 其中f s f s f s 是w...
WC 2018 州區劃分
給乙個無向圖 g v,e 滿足 v 21 對於某一種將 g v,e 劃分為k個的有序集合方案,若每乙個子集 g i v i,e i e i 都不存在尤拉迴路,則會對答案貢獻為 其中,x 為集合元素,w x 為元素 x 的權值。題解 被題意坑成cu 我還是太菜了 其實很顯然我們會得到乙個 dp 設 f...
WC2018 州區劃分
題目 就當那個判斷乙個州不合法的條件是存在尤拉迴路吧 一張無向圖存在尤拉迴路的條件是 圖連通不存在度數為奇數的點 於是我們列舉每乙個子集,可以在 o 2 nn 2 的時間內判斷乙個集合是否能獨立成為乙個州 之後我們設 dp i 表示選取狀態為 i 的時候的答案,s i 為這個狀態對應的城市的人口之和...