第一次想出多项式题。
其实去年就想出来了,今年再推一遍。
考虑一个式子,([x^y]prod_{i=1}^n(1+x+x^2+...+x^{a_i}))
注意到后面和(frac{1}{1-x})长得很像,所以把后面的(1+x+x^2+...+x^{a_i})拆成((1+x+x^2+....)-(x^{a_i+1}+....)=frac{1-x^{a_i+1}}{1-x})
令(b_i=a_i+1)原式(=[x^y]prod_{i=1}^n(frac{1-x^{b_i}}{1-x}))
考虑询问怎么求。
注意到在一次询问内,无论(b_i)改成多少,(frac{1}{1-x})的次数永远是(n)。
令(p(x)=prod_{i=1}^nfrac{1-x^{b_i}}{1-x})
先把(p(x))乘以(frac{1}{1-x})表示取前缀和。
所以询问要我们求的:([x^y]p(x)frac{1-x^z}{1-x^{b_i}}),其中(z)是原题的(x+1)
把下面展开,就是要我们求([x^y]p(x)(1-x^z)(1+x^{b_i}+x^{2b_i}+.....))
枚举((1-x^z))取哪个项,则问题转化成(O(q))组询问:(p(x)(1+x^{b_i}+x^{2b_i}+.....))的某项系数。
实际上就是哈希冲突。
当(b_igeq sqrt{10^5}),由于询问系数是(O(10^5))级别,可以暴力计算。
当(b_i<sqrt{10^5}),由于可能的(b_i)只有(O(sqrt{10^5}))种,可以预处理出每种(b)的答案。
令(f_{i,j})表示(y=i,b_i=j)的答案,可以递推求。
求([x^y]1-x^{b_i})是个经典问题(付公主的背包),求出((frac{1}{1-x})^{n+1})可以按照生成函数的定义。
然后把([x^y]1-x^{b_i})乘以((frac{1}{1-x})^{n+1})就是(p)。
最终时间复杂度(O(nsqrt{n}))。
感觉没什么细节,但是不知道为啥调了这么久
#include<bits/stdc++.h>
using namespace std;
#define mo 998244353
#define N 500010
#define ll unsigned long long
#define int long long
#define pl vector<int>
int qp(int x,int y){
int r=1;
for(;y;y>>=1,x=1ll*x*x%mo)
if(y&1)r=1ll*r*x%mo;
return r;
}
int rev[N],v,le,w[N];
void deb(pl x){
for(int i=0;i<x.size();i++)
printf("%lld ",x[i]);
puts("");
}
void init(int n){
v=1;
le=0;
while(v<n)le++,v*=2;
for(int i=0;i<v;i++)
rev[i]=(rev[i>>1]>>1)|((i&1)<<(le-1));
int g=qp(3,(mo-1)/v);
w[v/2]=1;
for(int i=v/2+1;i<v;i++)
w[i]=1ull*w[i-1]*g%mo;
for(int i=v/2-1;~i;i--)
w[i]=w[i*2];
}
void fft(int v,pl &a,int t){
static unsigned long long b[N];
int s=le-__builtin_ctz(v);
for(int i=0;i<v;i++)
b[rev[i]>>s]=a[i];
int c=0;
w[0]=1;
for(int i=1;i<v;i*=2,c++)
for(int r=i*2,j=0;j<v;j+=r)
for(int k=0;k<i;k++){
int tx=b[j+i+k]*w[k+i]%mo;
b[j+i+k]=b[j+k]+mo-tx;
b[j+k]+=tx;
}
for(int i=0;i<v;i++)
a[i]=b[i]%mo;
if(t==0)return;
int iv=qp(v,mo-2);
for(int i=0;i<v;i++)
a[i]=1ull*a[i]*iv%mo;
a.resize(v);
reverse(a.begin()+1,a.end());
}
pl operator *(pl x,pl y){
int s=x.size()+y.size()-1;
if(x.size()<=20||y.size()<=20){
pl r;
r.resize(s);
for(int i=0;i<x.size();i++)
for(int j=0;j<y.size();j++)
r[i+j]=(r[i+j]+x[i]*y[j])%mo;
return r;
}
init(s);
x.resize(v);
y.resize(v);
fft(v,x,0);
fft(v,y,0);
//deb(x);
//deb(y);
for(int i=0;i<v;i++)
x[i]=x[i]*y[i]%mo;
fft(v,x,1);
x.resize(s);
return x;
}
void inv(int n,pl &b,pl &a){
if(n==1){
b[0]=qp(a[0],mo-2);
return;
}
inv((n+1)/2,b,a);
static pl c;
init(n*2);
c.resize(v);
b.resize(v);
for(int i=0;i<n;i++)
c[i]=a[i];
fft(v,c,0);
//deb(c);
fft(v,b,0);
//deb(b);
for(int i=0;i<v;i++)
b[i]=1ll*(2ll-1ll*c[i]*b[i]%mo+mo)%mo*b[i]%mo;
//deb(b);
fft(v,b,1);
b.resize(n);
//deb(b);
}
void ad(pl &x,pl y,int l){
x.resize(max((int)x.size(),(int)y.size()+l));
for(int i=0;i<y.size();i++)
x[i+l]=(x[i+l]+y[i])%mo;
}
pl operator +(pl x,pl y){
ad(x,y,0);
return x;
}
pl iv(pl x){
pl y;
int n=x.size();
y.resize(n);
inv(n,y,x);
y.resize(n);
return y;
}
pl operator -(pl x,pl y){
int s=max(x.size(),y.size());
x.resize(s);
y.resize(s);
for(int i=0;i<s;i++)
x[i]=(x[i]-y[i]+mo)%mo;
return x;
}
pl qd(pl x){
pl y;
int n=x.size();
y.resize(n-1);
//deb(x);
for(int i=0;i<n-1;i++)
y[i]=x[i+1]*(i+1)%mo;
//deb(y);
return y;
}
pl jf(pl x){
int n=x.size();
pl y;
y.resize(n+1);
for(int i=1;i<=n;i++)
y[i]=x[i-1]*qp(i,mo-2)%mo;
return y;
}
pl ln(pl x){
int n=x.size();
pl y=qd(x),z=iv(x);
y=y*z;
y=jf(y);
y.resize(n);
return y;
}
char bf[100];
void wr(int x){
if(!x){
putchar('0');
putchar(' ');
return;
}
int ct=0;
while(x){
bf[++ct]=x%10;
x/=10;
}
for(int i=ct;i;i--)
putchar(bf[i]+'0');
putchar('
');
}
void gt(int n,pl &y,pl x){
if(n==1){
y.resize(1);
y[0]=1;
return;
}
gt((n+1)/2,y,x);
pl z=x,a;
z.resize(n);
y.resize(n);
a.resize(1);
a[0]=1;
y=y*(a-ln(y)+z);
y.resize(n);
}
pl ep(pl x){
pl y;
int n=x.size();
gt(n,y,x);
return y;
}
void put(pl a){
for(int i=0;i<a.size();i++)
printf("%lld ",a[i]);
puts("");
}
int n,a[N],q,ii[N],c[N],jc[N],ij[N];
signed g[N/5+10][400];
pl f;
void gt(int m){
f.resize(m+1);
for(int i=1;i<=m;i++)
for(int j=i;j<=m;j+=i)
f[j]=(f[j]+c[i]*(mo-ii[j/i]))%mo;
f=ep(f);
}
int cc(int y,int x){
return jc[y]*ij[x]%mo*ij[y-x]%mo;
}
int qu(int a,int b){
if(a<0)
return 0;
if(b<400)
return g[a][b];
else{
int ans=0;
for(int j=a;j>=0;j-=b)
ans=(ans+f[j])%mo;
return ans;
}
}
signed main(){
jc[0]=ij[0]=1;
for(int i=1;i<N;i++){
ii[i]=qp(i,mo-2);
jc[i]=jc[i-1]*i%mo;
}
ij[N-1]=qp(jc[N-1],mo-2);
for(int i=N-1;i;i--)
ij[i-1]=ij[i]*i%mo;
scanf("%lld%lld",&n,&q);
int va=1;
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
a[i]++;
va=va*a[i]%mo;
}
pl d;
d.resize(100010);
for(int i=0;i<100010;i++)
d[i]=cc(n+i,n);
for(int i=1;i<=n;i++)
c[a[i]]++;
gt(100010);
f=f*d;
for(int j=1;j<400;j++)
for(int i=0;i<100010;i++){
if(i>=j)
g[i][j]=(g[i-j][j]+f[i])%mo;
else
g[i][j]=f[i];
}
for(int i=1;i<=q;i++){
int p,x,y,ans=0;
scanf("%lld%lld%lld",&p,&x,&y);
y--;
x++;
ans=(ans+qu(y,a[p]))%mo;
ans=(ans-qu(y-x,a[p])+mo)%mo;
int vv=va*ii[a[p]]%mo*x%mo,vs=vv;
vs=(vs-ans+mo)%mo;
printf("%lld
",vs*qp(vv,mo-2)%mo);
}
}