zoukankan      html  css  js  c++  java
  • 洛谷7111

    第一次想出多项式题。
    其实去年就想出来了,今年再推一遍。
    考虑一个式子,([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);
    	}
    }
    
  • 相关阅读:
    python爬虫 -掘金
    python 爬取简书评论
    python爬取知乎评论
    python 爬取链家
    python爬虫获取下一页
    python正则找到字符串里面的数字
    faker切换user-agent
    python 爬虫可视化函数,可以先看看要爬取的数据是否存在
    acwing 471. 棋盘 解题记录
    ACWING 95 费解的开关 解题记录
  • 原文地址:https://www.cnblogs.com/ctmlpfs/p/14436472.html
Copyright © 2011-2022 走看看