​http://www.ifrog.cc/acm/problem/1032​

1032 - A-B

Time Limit:1s Memory Limit:128MByte

Submissions:680Solved:126

DESCRIPTION

你有nn个球,需要把他们放到mm个盒子里。
要求拥有最多球的盒子唯一,问方案数。

INPUT

一行两个数n,mn,m.(n,m≤500n,m≤500)

OUTPUT

一行一个数,表示方案数。 答案对9982443533取模。

SAMPLE INPUT

5 2

SAMPLE OUTPUT

6

SOLUTION

​“玲珑杯”ACM 热身赛 # 2.5​

 

今天补了这题,是以前一直遗漏的题,还是最怕的题。

但是离散数学老师真的教了我很多这些方程的解的个数。thx~

要做这题,可以先做这题。

​http://codevs.cn/problem/5652/​

 

这题可以考虑用容斥原理来解。

首先,暴力枚举,假如1号箱子的球的数量是最多,设为val

那么原问题是x1 + x2 + x3 + x4 .... + xm = n的。设定了1号最多而且是val的话

就是x2 + x3 + x4 + ..... + xm = n - val的解,其中 0 <= xi < val

这个问题的解,要用容斥原理。

先求出这个问题,一共有多少个解,就是先管0 <= xi。显然是C(n - val + m - 2, m - 2)个、如果这个不懂的话,

可以看看这个

但是有很多不符合的解。

然后暴力枚举有k个数是大于等于val的,这些就是不合法的解了。对于奇数个,我们将其减去,偶数个,加上来。

 

注意判断m = 1的话,ans = 1.因为我这里是用到了m - 2,所以你、m要>=2

然后这只是最大值在1号时候的情况。所以最后要乘上m。

 

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;


#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int MOD = 998244353;
LL quick_pow(LL a, LL b, LL MOD) { //求解 a^b%MOD的值
LL base = a % MOD;
LL ans = 1; //相乘,所以这里是1
while (b) {
if (b & 1) {
ans = (ans * base) % MOD; //如果这里是很大的数据,就要用quick_mul
}
base = (base * base) % MOD; //notice。注意这里,每次的base是自己base倍
b >>= 1;
}
return ans;
}

LL C(LL n, LL m, LL MOD) {
if (n < m) return 0; //防止sb地在循环,在lucas的时候
if (n == m) return 1;
LL ans1 = 1;
LL ans2 = 1;
LL mx = max(n - m, m); //这个也是必要的。能约就约最大的那个
LL mi = n - mx;
for (int i = 1; i <= mi; ++i) {
ans1 = ans1 * (mx + i) %MOD;
ans2 = ans2 * i % MOD;
}
return (ans1 * quick_pow(ans2, MOD - 2, MOD) % MOD); //这里放到最后进行,不然会很慢
}
int n, m;
void work() {
int n, m;
cin >> n >> m;
if (m == 1) {
cout << 1 << endl;
return;
}
assert(n > 0);
assert(m > 0);
LL ans = 0;
for (int val = 1; val <= n; ++val) {
LL tans = C(n - val + m - 2, m - 2, MOD);
for (int k = 1; k <= m - 1; ++k) {
if (k & 1) {
tans = (tans + MOD - C(m - 1, k, MOD) * C(n - val - k * val + m - 2, m - 2, MOD) % MOD) % MOD;
} else {
tans = (tans + C(m - 1, k, MOD) * C(n - val - k * val + m - 2, m - 2, MOD) % MOD) % MOD;
}
}
ans += tans;
assert(ans >= 0);
ans %= MOD;
}
assert(ans * m >= 0);
cout << (ans * m) % MOD << endl;
}

int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
work();
return 0;
}

View Code