JZOJ5728 簡單計數

2021-08-20 04:46:46 字數 2736 閱讀 2114

乍一看不是很會。

先考慮不是環怎麼做。

考慮分類地計數,即把方案歸到某一型別裡,再分別計算每乙個型別的數量來求答案。

最終一種方案肯定有若干段相同顏色段,我們可以直接考慮每一種顏色的劃分貢獻,然後再算出他們組合起來的方案數。

具體地,我們計算出f(i,j)表示把i個相同的球分成j段的貢獻和,一種方案貢獻為每段大小乘積。然後,我們把同顏色的i個球縮成j個,然後問題就變成要計算有多少種不同的排列方案,使得相同顏色的球不相鄰,設為f

設a[i]表示顏色i分成的段數,那麼答案就是∑a

[1..n]

∏if(

c[i]

,a[i

])∗f

(a[1..n]

) ∑a[

1..n]∏

if(c

[i],

a[i]

)∗f(

a[1..n])

,其中f就是排列方案。

考慮f怎麼求,我們可以做容斥。對於一種a[1..n],考慮列舉一些相鄰的同顏色球再縮起來,設剩下每種球個數b[1..n],這些球可以亂放,那麼此時容斥貢獻是(∑

b[i]

)!∗∏

cb[i

]−1a

[i]−

1∗(−

1)a[

i]−b

[i]∗

1b[i

]!( ∑b

[i])

!∗∏c

a[i]

−1b[

i]−1

∗(−1

)a[i

]−b[

i]∗1

b[i]

!。這個容斥我們可以dp地計算,每次列舉a[i]和b[i]即可,我們還可以在中途把f(

c[i]

,a[i

])f (c

[i],

a[i]

)也算進去,這樣是沒有問題的。設f[i][j]表示做到顏色i,∑k

=1..ib

[k]=

j ∑k=

1..ib[

k]=j

的貢獻和,最後再乘j!

j !。

這樣不是環的做法就出來了,轉移的時候優化一下。

現在考慮環怎麼辦。我們可以用最小表示法,固定顏色1在開頭,且1不能結尾。算出所有方案再乘∑c

[i] ∑c[

i]。固定開頭我們只需要讓最後的j!

j

!變成(j

−1)!

( j−

1)!,而列舉b[1]的時候乘1(

b[1]

−1)!

1 (b

[1]−

1)!。固定結尾類似。不過這樣有個問題,如果顏色1分成k段,dp完乘∑c

c的時候,這種方案會被算k次,我們在開始的時候除即可。

然後就做完了。

實現的時候沒有減掉開頭和結尾都是1的方案,不知道為什麼減掉錯了,估計是已經容斥掉了吧…

#include

#include

#include

#include

#include

#include

//開 o2!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

using namespace std;

#define fo(i,j,k) for(i=j;i<=k;i++)

#define fd(i,j,k) for(i=j;i>=k;i--)

#define cmax(a,b) (a=(a>b)?a:b)

#define cmin(a,b) (a=(atypedef long long ll;

typedef double db;

const int n=5000+5,mo=1e9+7;

int fac[n],rev[n],f[105][105],f[55][n],sum[n],c[n],a,b,i,j,k,ans,re[n],n,trs[n];

int ksm(int

x,int

y) return ret;

}void predo(int n)

int c(int

m,int n)

int main()

predo(5e3);

f[0][0]=1;

fo(i,1,100)

fo(j,1,i)

fo(k,1,i)

f[i][j]=(f[i][j]+1ll*f[i-k][j-1]*k)%mo;

f[0][0]=1;

fo(i,0,n)

}fo(j,0,sum[i])

fo(b,1,c[i+1])

f[i+1][j+b]=(f[i+1][j+b]+1ll*f[i][j]*trs[b])%mo;

}fo(j,0,sum[n])

ans=(ans+1ll*f[n][j]*fac[j-1])%mo;

printf("%d\n",1ll*ans

*sum[n]%mo);

}

jzoj 4257 著色 組合計數

description 有個電子工程系的學生從小喜歡塗顏色。現在他買了本塗色書和k種不同的顏料開始塗色。有趣的是它並不喜歡色彩斑斕的圖案,所以一幅圖他最多隻會用3種不同的顏料。還有,他不會把兩個相鄰區域塗成同樣的顏色。當兩個區域的邊界至少有乙個共同點時兩個區域是相鄰的。如下圖,區域3和4是相鄰的,區...

jzoj1404 菱形內的計數 模擬

給出乙個菱形中有一些邊,求有多少個中間沒有邊的平行四邊形。我們將乙個平行四邊形拆成兩個等腰三角形和乙個平行於菱形中間對角線的平行四邊形,我們可以判斷上面那個等腰三角形在判斷下面的。pragma gcc optimize o2 include include include include using...

jzoj 5562 簡單構造

description 一次歌唱比賽中,一位歌手剛剛結束表演,評委正在打分。一共有n 位評委,他們每人可以打1 分或0 分,第i 位評委希望歌手的得分為v i 評委們有特殊的控分技巧,他們會按乙個順序依次評分,第乙個評分的評委 會不管三七二十一打0 分。對於接下來的評委,假設前面a 位評委評分總和為...