可以用组合数学来做,一开始想复杂了
- 利用隔板法求所有结果
- 最终的公式:
- m = 0, 1时要特判,当时无方案数
ac代码
using ll = long long; void exgcd(ll a, ll b, ll &g, ll &x, ll &y) { if (!b) { g = a, x = 1, y = 0; return; } exgcd(b, a % b, g, y, x); y -= x * (a / b); } // ax=1(mod m) ll inverse(ll a, ll m) {//扩展欧几里得法求逆元,返回-1代表没有逆元 ll g, x, y; exgcd(a, m, g, x, y); return g == 1 ? (x % m + m) % m : -1; } #define mod(x) ((x) % _mod) const ll _mod = 1000000007; const int M = 2e3 + 10; ll f[M*M]; /*****************************************************************************/ class Solution { public: long long solve_bangbang(int n, int m, int k) { // write code here if ((m - 1) * k + m > n) return 0; if (m == 0) return 1; if (m == 1) return n - 1; f[0] = f[1] = 1; for (ll i = 2; i < M * M; ++i) f[i] = mod(f[i - 1] * i); ll ans = 0; for (ll i = (m - 1) * k; i <= n - m; ++i) { int indx1 = i - (m - 1) * k + m - 2, indx2 = indx1 - m + 2; ll d = n - m - i + 1; ll sum = mod(f[indx1] * inverse(mod(f[m - 2] * f[indx2]), _mod)); sum = mod(sum * d); ans = mod(ans + sum); } return mod(ans); } }; /*****************************************************************************/