Java教程

Solution AT987

本文主要是介绍Solution AT987,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
  • \(\mathtt{description}\):

Link
\(t\) 组询问,每组给出 \(n,k\le 10^5\),求 \(\begin{aligned}\sum\limits_{i=0}^{k}\dbinom{n}{i}\end{aligned}\),
\(t\le 10^5\)。

  • \(\mathtt{Solution}\):

\(n\to n+1\) 时:

\[\begin{aligned}\sum\limits_{i=0}^{k}\dbinom{n+1}{i}&=\sum\limits_{i=0}^{k}\begin{pmatrix}\dbinom{n}{i}+\dbinom{n}{i-1}\end{pmatrix}\\&=2\sum\limits_{i=0}^{k}\dbinom{n}{i}-\dbinom{n}{k}\end{aligned} \]

移项反解得 \(n\to n-1\) 时:

\[\begin{aligned}\sum\limits_{i=0}^{k}\dbinom{n-1}{i}=\dfrac{\sum\limits_{i=0}^{k}\dbinom{n}{i}+\dbinom{n}{k}}{2}\end{aligned} \]

\(k\to k+1\) 时:

\[\begin{aligned}\sum\limits_{i=0}^{k+1}\dbinom{n}{i}=\sum\limits_{i=0}^{k}\dbinom{n}{i}+\dbinom{n}{k+1}\end{aligned} \]

同理,\(k\to k-1\) 时:

\[\begin{aligned}\sum\limits_{i=0}^{k-1}\dbinom{n}{i}=\sum\limits_{i=0}^{k}\dbinom{n}{i}-\dbinom{n}{k+1}\end{aligned} \]

注意到上面四个转移式的余项都为单个组合数,而预处理阶乘及逆元计算组合数时 \(O(1)\) 的,所以上述四个转移也是 \(O(1)\) 的。

莫队即可,复杂度 \(O(n\sqrt n)\)。

#include <bits/stdc++.h>
#define int long long
namespace mystd {
	inline int read() {
	    char c = getchar();
	    int x = 0, f = 1;
	    while (c < '0' || c > '9') f = (c == '-') ? -1 : f, c = getchar();
	    while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + c - '0', c = getchar();
	    return x * f;
	}
	inline void write(int x) {
	    if (x < 0) x = ~(x - 1), putchar('-');
	    if (x > 9) write(x / 10);
	    putchar(x % 10 + '0');
	}
}
using namespace std;
using namespace mystd;

const int maxn = 2e5 + 200;// 不知道为啥要开大的空间,不然就过不去样例
const int mod = 1e9 + 7;
int n, l, r, b, c, mx, ans[maxn], fac[maxn], inv[maxn], ifac[maxn];
struct qry {
	int l, r, id;
	bool operator < (const qry &rhs) const {
		return l / b == rhs.l / b ? r < rhs.r : l < rhs.l;
	}
} q[maxn];

int C(int n, int m) { return fac[n] * ifac[m] % mod * ifac[n - m] % mod; }
void addr() { c = ((c * 2 % mod - C(r++, l)) % mod + mod) % mod; }
void delr() { c = inv[2] * ((c + C(--r, l)) % mod) % mod; }
void addl() { c = ((c - C(r, l--)) % mod + mod) % mod; }
void dell() { c = (c + C(r, ++l)) % mod; }

signed main() {
	n = read(), b = sqrt(n); 
	for (int i = 1; i <= n; i++) {
		q[i] = (qry) { read(), read(), i };
		swap(q[i].l, q[i].r);
		mx = max(mx, q[i].r);
	}
	sort(q + 1, q + n + 1);
	r = 1, c = 1;
	fac[0] = inv[1] = ifac[0] = 1;
	for (int i = 1; i <= mx; i++) {
		if (i >= 2) inv[i] = (mod - mod / i) * inv[mod % i] % mod;
		fac[i] = fac[i - 1] * i % mod;
		ifac[i] = ifac[i - 1] * inv[i] % mod;
	}
	for (int i = 1; i <= n; i++) {
		while (l > q[i].l) addl();
		while (l < q[i].l) dell();
		while (r < q[i].r) addr();
		while (r > q[i].r) delr();
		ans[q[i].id] = c;
	}
	for (int i = 1; i <= n; i++) write(ans[i]), puts("");
	return 0;
}

这篇关于Solution AT987的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!