玲珑杯 1032 A-B
Time Limit:1s?Memory Limit:128MByte
Submissions:528Solved:105
DESCRIPTION你有n個球,需要把他們放到m個盒子里。要求擁有最多球的盒子唯一,問方案數。
INPUT
一行兩個數n、m(n、m≤500)
OUTPUT
一行一個數,表示方案數。答案對998244353取模。
SAMPLE INPUT
5 2
SAMPLE OUTPUT
6
【解題方法1】
dp。
【參考blog】感謝http://blog.csdn.net/yhyyxt/article/details/52549053
dp[i][j]表示i個盒子里面一共放了j個球的情況。
假設球數最多的盒子里面放了k個球,那么剩下的m-1個盒子里面只能放n-k個球,每個盒子最多[0,k-1]個球。
dp[i][j] = ∑dp[i-1][j-x], x∈[0, k]。
用sum[i][j]來求dp[i][j]的前綴和來優化一下。
【AC 代碼1】
// //Created by just_sort 2016/9/25 15:11 //Copyright (c) 2016 just_sort.All Rights Reserved //#include <set> #include <map> #include <queue> #include <stack> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; const ll mod = 998244353; ll dp[505][505]; ll sum[505][505]; int main() {int n,m;while(scanf("%d%d",&n,&m)!=EOF){dp[0][0] = 1LL;for(int i=0; i<=n; i++) sum[0][i] = 1;ll ans = 0;for(int k=0; k<=n; k++){for(int i=1; i<m; i++){for(int j=0; j<=n; j++){dp[i][j] = 0;dp[i][j] = (sum[i-1][j] - (j-k>=0 ? sum[i-1][j-k]:0) + mod)%mod;sum[i][j] = ((j==0 ? 0: sum[i][j-1]) + dp[i][j])%mod;}}ans = (ans + m*dp[m-1][n-k])%mod;}printf("%lld\n",ans);}return 0; }【解題方法2】
組合數學,容斥!
【這個公式有錯誤】首先ans應該是乘以盒子的數量m,然后里面-的部分應該是*(-1)^k,容斥奇數加偶數減,并且還有一個問題就是n個球放在m個盒子里面,盒子可以為空的方案數的求法,可以參考這篇文章:http://wenku.baidu.com/link?url=snRwVkBTJ0FUvHuU11v_Cmp4BzqUCvuayU27ZSjupARpk_qwn_EyuRpcLamO2pJfDODKpPCaDphlGFkUSvKogeuGPQUD4O-ujDaY24JKEpu
具體公式如下:ps:公式c(n+num-1,n-1)的由來(高中學過的)
將num個相同的紅球放到n個盒子里去,每個盒子可以裝多個球,也可以不裝球,問有多少種放球的方式?
將設每個盒子里面原本就有1個球,將這n個球取出,和num個球混合在一起,那么球的總數就是m=num+n,我們要求的就轉化為將m個相同的紅球放到n個盒子里的方法有多少種?每個盒子至少有一個球!答案顯然就是c(m-1,n-1)
【AC 代碼】
// //Created by just_sort 2016/9/25 15:11 //Copyright (c) 2016 just_sort.All Rights Reserved //#include <set> #include <map> #include <queue> #include <stack> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; const ll mod = 998244353; ll C[1050][1050]; ll work(int x,int y){if(x+y-1<0 || y-1<0) return 0;return C[x+y-1][y-1]; }int main(){int n,m;while(scanf("%d%d",&n,&m)!=EOF){C[0][0] = 1;C[1][0] = C[1][1] = 1;for(int i=2; i<=1000; i++){C[i][0] = 1;for(int j=1; j<=1000; j++){C[i][j] = (C[i-1][j] + C[i-1][j-1])%mod;}}ll ans = 0;for(int x=0; x<=n; x++){for(int k=1; k<m; k++){ll sum = work(n-x*(k+1),m-1);ans = (ans + (k%2==1?1:-1)*C[m-1][k]*sum%mod)%mod;ans = (ans + mod)%mod;}}ans = (work(n,m) - ans + mod)%mod;ans = m * ans;printf("%lld\n",ans);}return 0; }
總結
以上是生活随笔為你收集整理的玲珑杯 1032 A-B的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Mac如何查看隐藏文件夹
- 下一篇: 国密SSL协议之双证书体系