csp2019 Emiya家今天的飯題解

2022-04-12 02:23:37 字數 2081 閱讀 9082

qwq

由於窩太菜了,實在是不會,所以在題解的幫助下過掉了這道題。

寫此部落格來整理一下思路

傳送簡化一下題意:現在有\(n\)行\(m\)列數,選\(k\)個數的合法方案需滿足:

1.一行最多選乙個

2.一列最多選\(\lfloor \frac \rfloor\)個數

當然,如果你在某一行裡選了0,就相當於沒有在這一行裡選數

選一次對答案的貢獻是你選的所有不為零的數的乘積。對於任意的\(k\),只要有合法方案,就能取。

(希望沒有把題目變得更複雜叭)

根據上面的要求,我們發現\(k\)的取值範圍是\([1,n]\)。而且根據要求2,如果某個方案在滿足1的前提下,是不合法的,那麼這個方案裡面一定有且僅有1列選了超出\(\lfloor \frac \rfloor\)個數,因為不可能有兩列選的數同時超過\(\lfloor \frac \rfloor\)個。我們現在知道了不合法方案的乙個特徵,那麼我們不妨試試總方案數-不合法方案數這個思路。

因為 滿足1情況的總方案數-滿足1而且不合法的方案數=亂選方案數-不滿足1或不滿足2的方案數 ,所以我們接下來計算方案數都在滿足1的條件下來計算。

計算總方案數:設\(all[i][j]\)表示前\(i\)行,每行至多選乙個,一共選了\(j\)個的方案數,那麼\(all[i][j]=all[i-1][j]+\sum_^m\)。用\(sum[i]\)表示第\(i\)行所有數的和,那麼\(all[i][j]=all[i-1][j]+all[i-1][j-1] \times sum[i]\)

我們再來看看不合法方案怎麼算。上面說到乙個不合法方案一定只有1行選的數超過了\(\lfloor \frac \rfloor\)個,所以我們可以列舉每一列。但是我們不知道\(k\)。那麼我們可以設\(no[i][j][l]\)表示前\(i\)行,該列選了\(j\)個,其他列選了\(l\)個。\(no[i][j][l]=no[i-1][j][l]+no[i-1][j-1][l]\times a[i][j]+no[i-1][j][l-1] \times(sum[i]-a[i][j])\)這樣就可以由\(j,l\)確定唯一的\(k\)。列舉列:\(o(m)\),列舉\(i\):\(o(n)\),因為選數的個數最多是\(n\),所以列舉\(j,l\)都是\(o(n)\),總複雜度\(o(mn^3)\)

顯然是不夠的,需要優化。發現我們其實並不需要具體的\(k\),只需要知道當前列和其他列選的數的差值即可。為什麼呢?不妨設當前列選的數為\(x+j\)個,其他列選的數為\(x\)個,那麼一共選的數就是\(2x+j\)個。這裡\(x\)取值任意(只要合法就行),所以可以\(2x+j\)覆蓋所有的\(k\)。所以設\(no[i][j]\)表示前\(i\)行,當前列舉的列比其他列多選了\(j\)個的方案數。

\(no[i][j]=no[i-1][j]+no[i-1][j-1] \times a[i][j]+no[i-1][j+1] \times (sum[i]-a[i][j])\)

注意這裡有個坑:列舉到第\(i\)行的時候,當前列最多會比其他列少\(i\)個數,所以\(j\)應該從\(-i\)開始列舉,而不是0。考慮到不能出現負下標,所以在**中將每個下標+n。

如果這個方案是不合法方案,那麼對應的\(j\)一定大於0。

最終答案就是\(sum_^n-\sum_^n\)

#include#include#include#include#include#include#includeusing namespace std;

typedef long long ll;

typedef unsigned long long ull;

inline ll read()

while(ch>='0'&&ch<='9')

return f?-x:x;

}const ll mod=998244353;

ll n,m,a[209][2009],sum[109],all[209][2009];

ll no[109][2109];

ll ans;

int main()

}for(int j=n+1;j<=2*n;j++)

ans=(ans-no[n][j]+mod)%mod;

} cout

}

csp2019 Emiya家今天的飯

作為提高組d2t 1d2t1 d2t1 比去年難 所以這道題我打的特別的差 這道題我們很顯然可以看到可以打乙個暴力 複雜度o n n o n n o n n 我考場上就達到了這裡 我太菜了 void dfs int u,ll plus dfs u 1,plus rep i,1 m if a u i ...

CSP2019 Emiya 家今天的飯

題面 luogu 題解 容斥 dp 首先題意是這樣的 給乙個 n times m 的矩陣,每一行只能選乙個,每一列選的總數不能超過選的總數的一半。求總方案數 考慮容斥 總方案數減去不合法方案數 總方案數顯然 設每一行的總數為 sum i ans prod sum i 1 1 減一是因為不能不做乙個菜...

CSP2019 Emiya 家今天的飯

鏈結 顯然根據性質最多的菜品不超過總數量的一半,可以考慮補集轉化 即計算有乙個菜品超過數量一半的方案數,再用總方案數減 總方案數顯然可以乙個揹包搞定 然而我去年就是因為總方案數沒求對掛了 然後考慮求超過一半的方案數 列舉當前哪個菜品是超過一半的 有乙個顯然的dp f 表示當前到第i行最多的菜品選了j...