日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

集合计数 (容斥原理)

發(fā)布時間:2023/12/10 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 集合计数 (容斥原理) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

心路:

{

想了個思路打出來硬干掉了樣例,然后發(fā)現(xiàn)是錯的....
當(dāng)時直接崩了...煩躁滴很
...其實這個思路和題解大方向上是一樣的,想到了用至少含k個的方案數(shù)減去含k+1個的加上k+2的。。。

然后再想怎么求至少含k個的方案數(shù)想到了讓集合含這k個數(shù)然后隨機組就行,但沒有想出來怎么求含這k個數(shù)的集合數(shù),而且就算求出來發(fā)現(xiàn)不能直接對一種情況乘,有重復(fù)計算的...

想到這...再想...再想...放棄->頹題解。T_T
頹完題解,發(fā)現(xiàn)我是把題目信息忽略了...2^n沒怎么用上;

}

題解

{

  往容斥上想,容斥的一般思路就是先找出單一滿足的,把問題簡單化(讓其限制變小),再逐步用容斥求解。

這題總思路就是先找至少含k個的(限制變少,能夠推式),再容斥。

再求至少含k個的時候,容易發(fā)現(xiàn)想要交出含這k個的,讓集合含這k個數(shù)在隨機組合一定能交出來.

問題來了:怎么求含特定k個數(shù)的集合總數(shù)呢?

把這k個數(shù)提取出來剩下的數(shù)隨機組,能夠組成的集合在把k個數(shù)補回去不就是答案嗎,所以有2^(n-k)種(含空集,實際指的是正好只含這K個數(shù)的集合),在讓這幾個集合隨機組一定是滿足能交成至少含k個數(shù)的方案。注意空集不是,所以是2^( 2^(n-k) )-1種。

舉個栗子:數(shù)據(jù)是4 2

以1,3為例,把1 3提取,剩下的數(shù)所組是{2},{4},{2,4},{空},其實就是{1,2,3},{1,3,4},{1,2,3,4},{1,3};這四個集合在隨機組成的方案中,空集相當(dāng)于哪個集合都沒取交集為空所以不符合。

求出1,3后乘上C(n,2)不就是交出來至少含k個的方案數(shù)了嗎?顯然不是,,,有重復(fù)的啊

比如1,3會求到{1,2,3,4}交{1,3,4},而1,4..3,4也會(當(dāng)時我就這崩了...)

看重復(fù)的有多少啊->對于求k個時交出來是k+1個的會算C(k+1,k)遍以此類推..所以在容斥時只要把重復(fù)的倍數(shù)減去就行。

設(shè)f(k)=C(n,k)*(? 2^( 2^(n-k) )-1 ),

答案就是f(k)*C(K,K)-C(K+1,K)*f(k+1)+C(k+2,k)*f(k+2)...;

預(yù)處理階乘和逆元,2^...這里也要預(yù)處理不然會WA(我也不知道為哈用快速冪求出的大數(shù)據(jù)就是不對)。

2^(2^(n-k))=( 2^(2^(n-k-1)) )^2,利用這個性質(zhì)倒推預(yù)處理出來就行了

f(k)?Ckk?f(k+1)?Ckk+1+f(k+2)?Ckk+2...f(n)?Ckn

}

#include<cstdio> #include<iostream> using namespace std; #define ll long long const int mod=1e9+7; const int maxn=1000010; int n,k; ll ans,f[maxn]; ll fac[maxn],inv[maxn],qtwo[maxn]; ll qpow(ll a,int b) {ll ans=1;while(b){if(b&1) ans=ans*a%mod;b>>=1;a=a*a%mod;}return ans; } void init() {fac[0]=1;for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i%mod;inv[n]=qpow(fac[n],mod-2);for(int i=n-1;i>=0;i--) inv[i]=inv[i+1]*(i+1)%mod;qtwo[n]=2;for(int i=n-1;i>=0;i--) qtwo[i]=qtwo[i+1]*qtwo[i+1]%mod; } void F(int x) {ll turn,kp;turn=qtwo[x]-1;f[x]=fac[n]*inv[x]%mod*inv[n-x]%mod*turn%mod; } void rongchi() {for(int i=k;i<=n;i+=2) ans=(ans+ fac[i]*inv[k]%mod*inv[i-k]%mod*f[i]%mod )%mod;for(int i=k+1;i<=n;i+=2) ans=(ans+mod- fac[i]*inv[k]%mod*inv[i-k]%mod*f[i]%mod )%mod; } int main() { //freopen("c.out","w",stdout);scanf("%d%d",&n,&k);init();for(int i=k;i<=n;i++) F(i);rongchi();printf("%lld",ans); } View Code

?

轉(zhuǎn)載于:https://www.cnblogs.com/three-D/p/11138164.html

總結(jié)

以上是生活随笔為你收集整理的集合计数 (容斥原理)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。