Description
对于一个
(
k
+
1
)
⋅
n
(k+1)\cdot n
(k+1)⋅n的矩阵,行编号从
0
0
0~
k
k
k,列编号从
1
1
1到
n
n
n,每次修改第一行元素,之后通过递推式
a
i
,
1
=
a
i
−
1
,
1
,
a
i
,
j
=
a
i
,
j
−
1
+
a
i
−
1
,
j
,
j
≥
2
a_{i,1}=a_{i-1,1},a_{i,j}=a_{i,j-1}+a_{i-1,j},j\ge 2
ai,1=ai−1,1,ai,j=ai,j−1+ai−1,j,j≥2
得到整个矩阵
a
i
,
j
a_{i,j}
ai,j,初始状态
a
0
,
1
=
.
.
.
=
a
0
,
n
=
0
a_{0,1}=...=a_{0,n}=0
a0,1=...=a0,n=0,给出
m
m
m次操作,操作分两种:
0 x y : 0\ x\ y: 0 x y:给 a 0 , x a_{0,x} a0,x加上 y y y
1 x : 1\ x: 1 x:查询 a k , x a_{k,x} ak,x
Input
第一行输入三个整数 n , m , k n,m,k n,m,k,之后 m m m行每行一个操作
( 1 ≤ n , m ≤ 1 0 5 , 1 ≤ k ≤ 40 , 1 ≤ x ≤ n , 1 ≤ y < 1 0 9 + 7 ) (1\le n,m\le 10^5,1\le k\le 40,1\le x\le n,1\le y<10^9+7) (1≤n,m≤105,1≤k≤40,1≤x≤n,1≤y<109+7)
Output
对于每次查询操作,输出 a k , x a_{k,x} ak,x,结果模 1 0 9 + 7 10^9+7 109+7
Sample Input
4 11 3
0 1 1
0 3 1
1 1
1 2
1 3
1 4
0 3 1
1 1
1 2
1 3
1 4
Sample Output
1
3
7
13
1
3
8
16
Solution
简单分析可知
a
[
k
]
[
x
]
=
∑
i
=
1
x
C
x
−
i
+
k
−
1
k
−
1
⋅
a
[
0
]
[
i
]
a[k][x]=\sum\limits_{i=1}^xC_{x-i+k-1}^{k-1}\cdot a[0][i]
a[k][x]=i=1∑xCx−i+k−1k−1⋅a[0][i],考虑恒等式
C
n
+
m
x
=
∑
i
=
0
x
C
n
i
C
m
x
−
i
C_{n+m}^x=\sum\limits_{i=0}^xC_n^iC_m^{x-i}
Cn+mx=i=0∑xCniCmx−i,进而有
a
[
k
]
[
x
]
=
∑
i
=
1
x
∑
j
=
0
k
−
1
C
x
j
C
k
−
1
−
i
k
−
1
−
j
a
[
0
]
[
x
]
=
∑
j
=
0
k
−
1
C
x
j
∑
i
=
1
x
C
k
−
1
−
i
k
−
1
−
j
a
[
0
]
[
i
]
a[k][x]=\sum\limits_{i=1}^x\sum\limits_{j=0}^{k-1}C_x^jC_{k-1-i}^{k-1-j}a[0][x]=\sum\limits_{j=0}^{k-1}C_x^j\sum\limits_{i=1}^xC_{k-1-i}^{k-1-j}a[0][i]
a[k][x]=i=1∑xj=0∑k−1CxjCk−1−ik−1−ja[0][x]=j=0∑k−1Cxji=1∑xCk−1−ik−1−ja[0][i]
显然第二个求和只是一个对
i
i
i的前缀求和,故可以用
k
k
k个树状数组维护
C
k
−
1
−
i
k
−
1
−
j
a
[
0
]
[
i
]
C_{k-1-i}^{k-1-j}a[0][i]
Ck−1−ik−1−ja[0][i]的前缀和,单次查询复杂度
O
(
k
l
o
g
n
)
O(klog_n)
O(klogn),总时间复杂度
O
(
k
m
l
o
g
n
)
O(kmlog_n)
O(kmlogn)
Code
#include<cstdio>
using namespace std;
typedef long long ll;
#define maxn 100005
#define mod 1000000007
int mul(int x,int y)
{
ll z=1ll*x*y;
return z-z/mod*mod;
}
int add(int x,int y)
{
x+=y;
if(x>=mod)x-=mod;
return x;
}
int inv[maxn];
void init(int n=1e5)
{
inv[1]=1;
for(int i=2;i<=n;i++)inv[i]=mul(mod-mod/i,inv[mod%i]);
}
struct BIT
{
#define lowbit(x) (x&(-x))
int b[maxn],n;
void init(int _n)
{
n=_n;
for(int i=1;i<=n;i++)b[i]=0;
}
void update(int x,int v)
{
while(x<=n)
{
b[x]=add(b[x],v);
x+=lowbit(x);
}
}
int query(int x)
{
int ans=0;
while(x)
{
ans=add(ans,b[x]);
x-=lowbit(x);
}
return ans;
}
}bit[40];
int C(int n,int m)
{
n=add(n,mod);
int ans=1;
for(int i=1;i<=m;i++)
{
int temp=add(n,mod-(m-i));
ans=mul(ans,mul(temp,inv[i]));
}
return ans;
}
int main()
{
init();
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
for(int i=0;i<k;i++)bit[i].init(n);
while(m--)
{
int op,x,y;
scanf("%d%d",&op,&x);
if(!op)
{
scanf("%d",&y);
for(int i=0;i<k;i++)bit[i].update(x,mul(C(k-x-1,k-i-1),y));
}
else
{
int ans=0;
for(int i=0;i<k;i++)ans=add(ans,mul(C(x,i),bit[i].query(x)));
printf("%d\n",ans);
}
}
return 0;
}