【题解】10.31模拟赛T3:青青草原的表彰大会

mac2025-12-29  7

solution

所有工资最多有 l o g 2 n log_2^n log2n个不同的数,设个数为 d d d 令不同的数为{ p i p_i pi}, p 1 , p 2 , . . . , p d p_1,p_2,...,p_d p1,p2,...,pd d p i , j dp_{i,j} dpi,j表示长度为 i i i p i = j p_i=j pi=j p p p数列个数 转移方程 d p i + 1 , j ∗ l + = d p i , j dp_{i+1,j*l}+=dp_{i,j} dpi+1,jl+=dpi,j c n t i = ∑ j = 1 n d p i , j cnt_i=\sum_{j=1}^{n}dp_{i,j} cnti=j=1ndpi,j 得到 a n s = ∑ i = 1 l o g 2 n c n t i ∗ C k − 1 i − 1 ans=\sum_{i=1}^{log_2^n}cnt_i*C_{k-1}^{i-1} ans=i=1log2ncntiCk1i1

Code:

#include <bits/stdc++.h> #define maxn 1000010 #define LL long long using namespace std; const LL qy = 1000000007; const int m = 22; int n, k; LL fac[maxn], inv[maxn], cnt[30], dp[23][maxn]; LL ksm(LL n, LL k){ if (!k) return 1; LL sum = ksm(n, k >> 1); sum = sum * sum % qy; if (k & 1) sum = sum * n % qy; return sum; } LL C(int n, int m){ return fac[n] * inv[n - m] % qy * inv[m] % qy; } int main(){ freopen("commend.in", "r", stdin); freopen("commend.out", "w", stdout); scanf("%d%d", &n, &k); fac[0] = 1; for (int i = 1; i < maxn; ++i) fac[i] = fac[i - 1] * i % qy; inv[maxn - 1] = ksm(fac[maxn - 1], qy - 2); for (int i = maxn - 2; i >= 0; --i) inv[i] = inv[i + 1] * (i + 1) % qy; for (int i = 1; i <= n; ++i) dp[1][i] = 1; for (int i = 1; i < m; ++i) for (int j = 1; j <= n; ++j) for (int l = j << 1; l <= n; l += j) (dp[i + 1][l] += dp[i][j]) %= qy; for (int i = 1; i <= m; ++i) for (int j = 1; j <= n; ++j) (cnt[i] += dp[i][j]) %= qy; LL ans = 0; for (int i = 1; i <= m && i <= k; ++i) (ans += cnt[i] * C(k - 1, i - 1) % qy) %= qy; printf("%lld\n", ans); return 0; }
最新回复(0)