【容斥原理經典題】
第i
ii個物品不能放在a
ia_i
ai箱子裡,求每個箱子有乙個物品的方案數
經典題目
之前做了一道題,需要crt
crtcr
t合併(此題)
也是要考慮到容斥,那題處理方式是利用dpdp
dp,因為有個類似上公升子串行的遞推關係,dp[
i]
dp[i]
dp[i
]表示第乙個不合法的情況,之後無論怎麼選都還是不合法。
此題類似,g(n
)g(n)
g(n)
表示有n
nn個不合法的方案數,f(n
)f(n)
f(n)
表示任意排列的方案數。
顯然如果有k
kk個不合法,方案數顯然為g(k
)=g(
k)∗f
(n−k
)g(k)=g(k)*f(n-k)
g(k)=g
(k)∗
f(n−
k),比賽的時候沒考慮到任意排列,如果不任意的話是不能夠這麼乘的,只有任意的時候才不會被影響。
不過顯然,這樣子處理的時候,可能會有多於k
kk個不合法,所以我們定義g(k
)g(k)
g(k)
為至少k
kk個不合法。
根據容斥原理,答案為∑i=
0n(−
1)ig
(i
)\sum\limits_^n (-1)^ig(i)
i=0∑n
(−1)
ig(i
)(至少有i
ii個不合法的情況,顯然包含g(i
+1
)g(i+1)
g(i+1)
,符合容斥原理的要求)。
最後求g(k
)g(k)
g(k)
的時候,令g[i
][j]
g[i][j]
g[i][j
]表示考慮前i
ii個物品不合法,有j
jj個不合法;
則有:g[i
][j]
=g[i
−1][
j]+g
[i−1
][j−
1]∗b
[i
]g[i][j]=g[i-1][j]+g[i-1][j-1]*b[i]
g[i][j
]=g[
i−1]
[j]+
g[i−
1][j
−1]∗
b[i]
,b [i
]b[i]
b[i]
表示要使當前盒子不合法,有幾種方法(不能放在該盒子的有幾個)。
因為資料較大,需要滾動陣列,或者用類似揹包逆推的方法。
#include
#define for(i,a,b) for(int i=a;i<=b;i++)
#define inf 0x3f3f3f3f
typedef
long
long ll;
using
namespace std;
const
int maxn =
3e5+10;
const
int maxm =
1e6+10;
const
int mod =
998244353
;ll f[maxn]
,g[maxn]
;ll a[maxn]
,x;int
main()
} ll ans=0;
for(
int i=
0,j=
1;i<=n;i++
,j*=-1
)ans=
(ans+
1ll*j*g[i]
*f[n-i]
)%mod;
cout<<
(ans+mod)
%mod<}
牛客練習賽64 D寶石裝箱
n 顆寶石裝進 n 個箱子使得 每個箱子中都有一顆寶石 其中第 i 顆寶石不能裝入第 ai 個箱子 求合法的裝箱方案數。總的裝箱方案為 n 答案 總方案數 sum f left i right 其中 f x 表示 x 個箱子不合法的方案數 我們定義 dp i j 表示前 i 個箱子有 j 個放了不合...
牛客練習賽64 題解
a 怪盜 1412題目描述 乙個長度為n m k包含n個數字1,m個數字2和k個數字4的陣列,最多可能有多少個子序列1412?如果乙個序列是陣列的子串行,當且僅當這個序列可以由陣列刪去任意個元素,再將陣列中的剩餘元素按順序排列而成。思路 將序列排列成111444441111222222,這樣可以得到...
牛客練習賽24 D
名字挺有意思的,排插樹,雖然這是個圖。算dijkstra的模版題,求最短路裡面最長的那條,因為到講台的距離總是取決於最短的那條路,但是又要求離講台最遠,那麼我們通過dijkstra計算出起始點到所有點的最短路然後遍歷找最大值就好。如下 include using namespace std type...