description
傳送門題解
看懂題需要一會…樸素的dp就可以列出乙個方程
f [m
ask]
=1r[
i]p∑
j∣k=
mask
f[j]
∗r[k
]p
f[mask]=\frac\sum_ f[j]*r[k]^p
f[mask
]=r[
i]p1
j∣k
=mas
k∑f
[j]∗
r[k]
p其中r[i
]r[i]
r[i]
表示i
ii狀態下的人數
那麼暴力列舉子集就是3
n3^n
3n的嚕然後發現這其實是乙個裸的子集卷積
於是就可以直接卷一下完事了…
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ll long long
#define mp(x,y) make_pair(x,y)
#define pll pair
#define pii pair
using
namespace std;
inline
intread()
while
(ch>=
'0'&&ch<=
'9')
return x*f;
}int stack[20]
;inline
void
write
(int x)if(
!x)int top=0;
while
(x)stack[
++top]
=x%10
,x/=10;
while
(top)
putchar
(stack[top--]+
'0');}
inline
void
pr1(
int x)
inline
void
pr2(
int x)
const
int maxn=22;
const
int mod=
998244353
;const
int maxmask=(1
<<21)
;int a[maxn]
,b[maxn]
;void
fwt(
int*y,
int len,
int on)
}int
pow_mod
(int a,
int b)
return ret;
}int f[maxn]
[maxmask]
,ok[maxmask]
,bin[25]
,w[maxn]
,r[maxmask]
,ct[maxmask]
;int c[maxn]
[maxmask]
,inv[maxmask]
;int n,m,p,mp[maxn]
[maxn]
;int du[maxn]
,rt[maxn]
;int
findrt
(int x)
voidad(
int&x,
int y)
intmain()
for(
int i=
1;i<=n;i++
)w[i]
=read()
;for
(int i=
0;i;i++)if
(ct[i]==1
)ok[i]=0
;bool tf=
false
;for
(int j=
1;j<=n;j++)if
(du[j]&1
) tf|
=(cnt!=1)
; ok[i]
&=tf;
r[i]
=pow_mod
(r[i]
,p);
if(ok[i])ad
(c[ct[i]
][i]
,r[i]);
inv[i]
=pow_mod
(r[i]
,mod-2)
;}for(
int i=
1;i<=n;i++
)fwt
(c[i]
,bin[n],1
);f[0][
0]=1
;fwt
(f[0
],bin[n],1
);int ans;
for(
int i=
1;i<=n;i++
)pr2
(f[n]
[bin[n]-1
]);return0;
}
LOJ 2340 WC2018 州區劃分
感覺是比較基礎的子集 dp.令 dp s 表示點集 s 構成的價值和,然後列舉最後乙個區域就行.也就是 dp s sum dp s t times frac k 化簡得 dp s times sum s k sum dp s t times sum t k 如何判斷尤拉迴路 所有點的度數都是偶數,就...
ssl2340 格仔遊戲 並查集
題目鏈結 有兩個人在玩遊戲,在乙個n n的矩陣的點上畫線,有如果有線封了圈那麼遊戲結束,給出一些操作,求在那一輪結束了遊戲,或沒有結束遊戲。用並查集把點相連,直到並查集形成環為止 include include using namespace std int n,m,x,y,father 40001...
LOJ 103 子串查詢 Hash
給定兩個字串 a 和 b 求 b 在 a 中的出現次數。這是一道 kmp 的模板題。不過 hash 是個好東西,可以用 hash 代替 kmp 演算法。預處理兩個字串的雜湊值,然後將 a 中所有長度為 len b 的子串的雜湊值與 b 的雜湊值比較即可。時間複雜度 o n m 與 kmp 演算法一樣...