考虑动态规划:$f(i)$ 表示有 $i$ 个顾客购买一血气球,实质上是背包。

我们使用退背包,对于修改,先退出,再加入即可。

我们发现 $C$ 很小,所以可以先用所有的情况即 $\prod_{i=1}^n a_i + b_i$,减去 $\sum_{i=0}^{C-1} f(i)$,这样时间复杂度是 $O(qC)$ 的,略微卡常。

我们也可以用多项式的角度取考虑,所求即为:

$$
\sum_{i=0}^{C-1} [x^i] \prod_{i=1}^n (a_i x + b_i)
$$

所谓插入即模拟了一个暴力乘法,删除即模拟了一个暴力除法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// ubsan: undefined
// accoders
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
const int maxn=1e6;
int n,m,C;
int a[maxn+5],b[maxn+5];
int f[25];
int s[25],st;
inline int Read(){
char ch=getchar();
while(ch<'0'||'9'<ch) ch=getchar();
int res=0;
while('0'<=ch&&ch<='9')
res=(res<<3)+(res<<1)+ch-'0',ch=getchar();
return res;
}
inline void Write(int x){
if(!x) puts("0");
else{
while(x) s[st++]=x%10,x/=10;
while(st) putchar('0'+s[--st]);
putchar('\n');
}
}
inline int Fpow(int x,int y){
int res=1;
for(;y;x=1ll*x*x%mod,y>>=1)
if(y&1) res=1ll*res*x%mod;
return res;
}
inline void Insert(int x){
for(int j=C-1;~j;j--){
f[j]=1ll*f[j]*b[x]%mod;
if(j) f[j]=(f[j]+1ll*f[j-1]*a[x])%mod;
}
}
inline void Delete(int x){
int tmp=Fpow(b[x],mod-2);
for(int j=0;j<C;j++){
if(j) f[j]=(f[j]-1ll*f[j-1]*a[x])%mod;
f[j]=1ll*f[j]*tmp%mod;
}
}
signed main(){
// const double tm=clock();
freopen("balloon.in","r",stdin);
freopen("balloon.out","w",stdout);
n=Read(),C=Read();
for(int i=1;i<=n;i++) a[i]=Read();
for(int i=1;i<=n;i++) b[i]=Read();
scanf("%d",&m);
int x,ans,res=1;
for(int i=1;i<=n;i++)
res=(1ll*res*(a[i]+b[i]))%mod;
f[0]=1;for(int i=1;i<=n;i++) Insert(i);
while(m--){
x=Read();
Delete(x);
res=1ll*res*Fpow(a[x]+b[x],mod-2)%mod;
a[x]=Read(),b[x]=Read();
Insert(x);
res=1ll*res*(a[x]+b[x])%mod;
ans=res;
for(int i=0;i<C;i++) ans=(ans-f[i])%mod;
Write((ans+mod)%mod);
}
// cerr<<(clock()-tm)/CLOCKS_PER_SEC;
return 0;
}