有\(n\)種顏色的小球,
每種顏色的小球有\(a_i\)個,即一共有\(\sum_^n a_i\)個小球。
現在要求把這些小球排同色不相鄰的方案數求解成一行,要求同種顏色的小球不相鄰。
求方案數,答案對\(10^9+7\)取模。 提交**:web
下面的演算法都只考慮同色小球之間無區別的方案數。
即可重排列的情況。
如果同色小球之間有區別,為不重排列,那麼對應乘上 \(\prod (a_i!)\) 即可。
從前往後列舉每種顏色的小球。
設\(f_\)表示考慮完前\(i\)種小球,存在\(j\)個違法相鄰的方案數。
轉移首先考慮將\(a_i\)個小球分為\(k\)段,一共\(\binom\)種方法。
這一共造成了\(a_i - k\)個新的不合法情況。
列舉把其中\(l\)塊插入原先的不合法位置之間,那麼一共消除了\(l\)個不合法相鄰。
這一共有\(\binom\)種選擇,剩下的塊有\(\binom\)種選擇。
所以轉移方程式:
\[f_ = \sum f_ \binom \binom \binom
\]其中\(sum = \sum_^ a_e\) ;
滿複雜度:\(o(n(\sum a)a_^2)\),但是非常不滿,實測跑 \(n,\sum a\leq 1000\)並不虛。
這種方法好寫好理解,但是適用性較窄(不方便新增整段權值)。
#include#define ll long long
#define maxn 2005
#define mod 1000000007
using namespace std;
ll n , q, x , sum , cur;
ll a[maxn] , fac[maxn] , c[maxn][maxn] , f[3][maxn];
void pre()
return;
}int main()
sum += a[i];
}cout《全部不相鄰的方案數 = 全部不相臨的排列數 - 1個相鄰的排列數 + 2個相鄰的排列數 ......
直接列舉不好算,單獨考慮一種小球的貢獻。
由於可重排列:\(p = \frac\),所以先只乘\(\frac\),最後乘上\((\sum a)!\)即可。
我們可以列出有\(a_i\)個小球的容斥多項式:
\[f(a_i) = \sum_ ^ (-1)^ \frace(a_i , i)
\]其中\(e(i,j)\)表示\(i\)個小球因為違法相鄰而實際只有\(j\)段的方案數。
顯然就是要保留\(i-1\)個間隔中的\(j-1\)個,所以\(e(i,j) = \binom\)。
把每種小球的容斥多項式卷積卷起來就可以得到總的容斥式。
對於最後的總容斥式的每一項,乘上對應的階乘(可重排列的分子),再加起來即可。
總時間複雜度:\(o(n(\sum a)a_)\)。
這種做法較難理解、容易寫錯,但是複雜度低,適用性好(新增權值直接在計算係數時乘上即可)。
//#include#define rg register
#define il inline
#define n 505
using namespace std;
const int mod = 1000000007 ;
int dp[10*n],c[n+5][n+5],e[n+5][n+5],fact[n+5],a[n+5],n,sum,ans;
int inv[n+5],inv_fact[n+5],coef[n+5];
il void pre()return ;
}il void upt(rg int &x,rg int y)
int main()
sum += a[sq]; //dp記錄的是最後的總容斥式的每一項係數.
} ans = 0;
for(rg int k = 0; k <= sum; k ++) upt(ans , 1ll * dp[k] * fact[k] % mod) ;
printf("%d\n" , ans) ; return 0;
}
不相鄰的組合個數
a 中選取m m個不相鄰的組合個數,即不存在兩個數j和j 1的組合。例如,n 4 m 2 n 4,m 2 有組合,a 中取mm 個不相鄰組合,其組合數為cmn m 1 cn m 1m。b 是一組不相鄰的組合,假設b 1 b1,令c1 b1,c 2 b2 1,c 3 b3 2,cm bm m 1 n ...
Python從列表中刪除相鄰和不相鄰的相同元素
相鄰元素是不相鄰元素中的一種特殊的存在,所以我們先來 不相鄰的相同元素的刪除。結果 list 1,2,3,4 第一種 list 1,2,3,3,4,1,1 new list for i in list if i not in new list 可以刪除重複元素,不管是否相鄰 print new li...
求不相鄰的最大子陣列和
參考 題目 給定乙個陣列a,求出一些數,使得每個元素在陣列a裡兩兩不相鄰,並且和最大。選擇第i個元素,那麼第i 1個元素一定不能選 不選擇第i個元素,那麼第二個元素既可以選,也可以不選 includeusing namespace std int main int selected 8 int no...