做题笔记 #4

题面

给定 \(n,m\),一共 \(T\) 组询问,求 \(\sum\limits_{k = 0}^m \binom nk \bmod{2333}\)

\(n,m\)\(10^9\) 级别,\(T\)\(10^5\) 级别。

解法:

先把 \(k\) 按照 \(\left\lfloor\frac kp \right\rfloor\) 分类

\[\sum_{k = 0}^m \binom nk = \sum_{i = 0}^{\lfloor \frac mp \rfloor - 1} \sum_{j = 0}^{p - 1} \binom{n}{ip + j} + \sum_{k = p\lfloor \frac mp\rfloor}^m \binom nk \]

再用 Lucas 定理展开:

\[\sum_{i = 0}^{\lfloor \frac mp \rfloor - 1} \binom{\lfloor \frac np\rfloor}{i} \sum_{j = 0}^{p - 1} \binom{n \bmod p}{j} + \sum_{k = p\lfloor \frac mp\rfloor}^m \binom{\frac np}{\frac kp}\binom{n \bmod p}{k \bmod p} \]

注意到 \(\sum\limits_{j = 0}^{p - 1} \binom{n \bmod p}{j}\) 用一行之和定理表示为 \(2^{n \bmod p}\)\(\binom{\frac np}{\frac kp}\) 始终为定值,而且可以用普通的 Lucas 来求,于是上式可改写为:

\[2^{n \bmod p} \sum_{i = 0}^{\lfloor \frac mp \rfloor - 1} \binom{\lfloor \frac np \rfloor}{i} + \binom{\frac np}{\frac kp} \sum_{k = 0}^{m \bmod p} \binom{n \bmod p}{k} \]

然后发现左边可以递归,右边 Lucas + 预处理。于是做完了。复杂度为 \(O(T log^2_p n)\)

总结一下

\(p\) 很小的时候,下指标求和可以用 Lucas 定理递归求解。

\(n \le m\) 的时候,可以用一行之和来求。

附上代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int long long
const int mod = 2333; 
ll n, m;
ll C[mod + 1][mod + 1], f[mod + 1][mod + 1];
ll lucas(int n, int m) {
	if(n < m) return 0;
	if(!m || n == m) return 1;
	return lucas(n / mod, m / mod) * C[n % mod][m % mod] % mod;
}
ll two[mod + 1];
ll calc(int n, int m) {
	if(m < 0) return 0;
	if(!n || !m) return 1; 
	if(n < mod && m < mod) return f[n][m];
	ll tmp = m / mod;
	return (f[n%mod][mod-1] * calc(n / mod, tmp - 1) % mod + lucas(n / mod, tmp) * f[n % mod][m % mod] % mod) % mod;
} 

void st(int n) {
	two[0] = 1; for(int i = 1; i <= n; ++i) two[i] = (two[i-1] << 1) % mod;
	C[0][0] = f[0][0] = 1;
	for(int j = 0; j <= n; ++j) f[0][j] = 1;
	for(int i = 1; i <= n; ++i) {
		C[i][0] = f[i][0] = 1;
		for(int j = 1; j <= i; ++j) C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % mod;
		for(int j = 1; j <= n; ++j) f[i][j] = (f[i][j - 1] + C[i][j]) % mod;
	}
}
signed main() {
	st(mod);
	int _; cin >> _;
	while(_--) {
		cin >> n >> m;
		printf("%lld\n", calc(n, m));
	}
	return 0;
}//98 2 10
posted @ 2025-03-25 19:12  花子の水晶植轮daisuki  阅读(20)  评论(0)    收藏  举报
https://blog-static.cnblogs.com/files/zouwangblog/mouse-click.js