写程序or打游戏(组合计数)
L-打游戏 or 写程序_河南萌新联赛2025第(七)场:郑州轻工业大学(重现赛)
星与条定理
将 m 个相同物品放入 r 个不同盒子" 的方法数是 C (m+r-1, r-1)
分析
1. 设定变量
假设在序列中,打游戏(1)出现了 i 次,那么写程序(0)就出现了 n-i 次(因为总事件数是 n)。
2. 必须的间隔
因为两个打游戏之间至少有 k 个写程序,所以 i 次打游戏之间有 (i-1) 个间隔,每个间隔至少需要 k 个 0。
这些是 "硬性要求",必须满足,所以总共用掉了 (i-1)×k 个 0。
3. 剩余的自由度
总共有 n-i 个 0,减去必须用掉的 (i-1)×k 个 0,剩下的 0 数量是:
剩余0 = (n-i) - (i-1)×k
这些剩下的 0 可以自由分配,没有数量限制(可以是 0 个或多个)
4. 分配剩余的 0(关键步骤)
这些剩余的 0 可以放在哪里?有 (i+1) 个位置可以放:
代码
using namespace std;
#define int long long
#define endl '\n'
#define PII pair<int, int>
#define LL long long
const int N = 2e6 + 10, M = 1e7, inf = 1e18;
const int mod = 1e9 + 7;LL fac[N], infac[N]; // C a b == a! / (*b! * (a - b)!) == a! * (b!)[逆元] * (a - b)![逆元]
// fac[a] = a! % mod; infac[b] = (b!)[逆元] LL qmi(LL a, LL k) {LL ans = 1;while (k) {if (k & 1) ans = ans * a % mod;k >>= 1;a = a * a % mod;}return ans;
}void intal(int n) {fac[0] = infac[0] = 1;for (int i = 1; i <= n; i ++ ) {fac[i] = fac[i - 1] * i % mod;infac[i] = infac[i - 1] * qmi(i, mod - 2) % mod;}
}int C(int a, int b) {if (a < b || a < 0 || b < 0) return 0;return fac[a] * infac[b] % mod * infac[a - b] % mod;
}void solve() {int n, k;cin >> n >> k;intal(n + k);int ans = 0;for (int i = 0; i <= n; i ++ ) {ans = (ans + C(i - (n - i - 1) * k + n - i, n - i)) % mod;}cout << ans << endl;}signed main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int T = 1;// cin >> T;while (T -- ) {solve();}return 0;
}