题目大意:
一个有
n
n
n个数的序列,下标为
1
,
2
,
.
.
,
n
−
1
,
n
1,2,..,n-1,n
1,2,..,n−1,n,有
m
m
m次操作,每次操作给出
l
,
r
,
k
l,r,k
l,r,k,使得在
[
l
,
r
]
[l,r]
[l,r]内的任意一个数
a
i
a_i
ai都累加上
C
(
i
+
k
−
l
,
k
)
C(i+k-l,k)
C(i+k−l,k)。
一开始所有
a
[
]
a[]
a[]为0。
问
m
m
m次操作之后,每个数分别是多少,答案对
1
e
9
+
7
1e9+7
1e9+7取模
1 ≤ n , m ≤ 5 × 1 0 5 , 0 ≤ k ≤ 20 1 ≤ n, m ≤ 5 × 10^5, 0 ≤ k ≤ 20 1≤n,m≤5×105,0≤k≤20
分析:
根据组合数的性质,
C
(
n
,
m
)
=
C
(
n
−
1
,
m
−
1
)
+
C
(
n
−
1
,
m
)
C(n,m) = C(n-1,m-1) + C(n-1,m)
C(n,m)=C(n−1,m−1)+C(n−1,m)
那么我们每次操作维护这个数列的
k
k
k 阶差分
然后做
k
k
k 阶前缀和即可求出每个数的变化
代码:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#define N 500050
using namespace std;
typedef long long ll;
const int MOD = 1e9 + 7;
ll C[N][25], ans[N][25];
int n, m;
void read(int &x)
{
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s >= '0' && s <= '9') { x = x * 10 + (s - '0'); s = getchar(); }
x = x * f;
}
void write(ll x)
{
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
int main()
{
freopen("sequence.in", "r", stdin);
freopen("sequence.out","w", stdout);
read(n); read(m);
C[0][0] = 1;
for (int i = 1; i <= n + 20; i++)
{
C[i][0] = 1;
for (int j = 1; j <= min(i, 20); j++) C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % MOD;
}
for (int i = 1; i <= m; i++)
{
int L, R, K;
read(L); read(R); read(K);
for (int j = 0; j <= K; j++) ans[L][j] = (ans[L][j] + C[K][K - j]) % MOD, ans[R + 1][j] = (ans[R + 1][j] - C[(R + 1) - L + K][K - j]) % MOD;
}
for (int i = 1; i <= n; i++)
for (int j = 0; j <= 20; j++)
ans[i + 1][j] = (((ans[i + 1][j] + ans[i][j] % MOD + MOD) + ans[i][j + 1]) % MOD + MOD) % MOD;
for (int i = 1; i <= n; i++) write((ans[i][0] % MOD + MOD) % MOD), printf("\n");
}