任意模数FFT & 第一类斯特林数模板

JZOJ 6054

//%%y
#include
#include
#include
#include
#include
#define fo(i,a,b) for(int i=(a);i<=(b);++i)
#define fd(i,b,a) for(int i=(b);i>=(a);--i)
#define mset(a,x) memset(a,x,sizeof(a))
#define mcpy(a,b) memcpy(a,b,sizeof(b))
using namespace std;
typedef long long ll;
typedef double db;
int read(){int n=0,p=1;char ch;for(ch=getchar();ch<'0' || ch>'9';ch=getchar())if(ch=='-') p=-1;for(;'0'<=ch && ch<='9';ch=getchar()) n=n*10+ch-'0';return n*p;}
const int N=4e5+5;
const ll mo=1e9+7;
ll qmi(ll x,ll n)
{
	ll t=1;
	for(x%=mo;n;n>>=1,x=x*x%mo) if(n&1) t=t*x%mo;
	return t;
}
void inc(ll &x,ll y){x=(x+y)%mo;}
int n,l,r;
ll fac[N],ifac[N],a[N],b[N];
const db pi=acos(-1);
struct Z
{
	db x,y;
	Z(db _x=0,db _y=0):x(_x),y(_y){}
	friend Z operator +(Z a,Z b){return (Z){a.x+b.x,a.y+b.y};}
	friend Z operator -(Z a,Z b){return (Z){a.x-b.x,a.y-b.y};}
	friend Z operator *(Z a,Z b){return (Z){a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x};}
	friend Z conj(Z a){return (Z){a.x,-a.y};}
}W[N];
int len,lg,bitrev[N];
void dft(Z *a,int sig=1)
{
	fo(i,0,len-1) if(i>1;i<=len;i<<=1,gap>>=1)	
		for(int j=0;j>1),*w=sig>0?W:W+len;
			for(int k=0;k<(i>>1);++k,++l,++r,w=sig>0?w+gap:w-gap)
			{
				Z u=*l,v=*r * *w;
				*l=u+v,*r=u-v;
			}
		}
	if(sig==-1) fo(i,0,len-1) a[i].x=a[i].x/len,a[i].y=a[i].y/len;
}
void fft(ll *c,ll *a,ll *b)
{
	W[0]=Z(1,0);
	fo(i,1,len) W[i]=Z(cos(2*pi*i/len),sin(2*pi*i/len));
	fo(i,0,len-1) bitrev[i]=(bitrev[i>>1]>>1)|((i&1)<<(lg-1));
	static Z A[N],B[N],C[N],D[N];
	fo(i,0,len-1)
	{
		a[i]=(a[i]+mo)%mo,b[i]=(b[i]+mo)%mo;
		A[i]=Z(a[i]>>15,a[i]&32767);
		B[i]=Z(b[i]>>15,b[i]&32767);
	}
	dft(A);dft(B);
	for(int i=0;i>1);
	for(len=1,lg=0;len<=n;len<<=1,++lg);
	for(ll i=0,t=1;i<=(n>>1);++i,t=t*(mo-(n>>1))%mo)
		g[i]=f[i]*fac[i]%mo,h[(n>>1)-i]=t*ifac[i]%mo;
	fo(i,(n>>1)+1,len-1) g[i]=h[i]=0;
	fft(g,g,h);
	fo(i,0,n>>1) g[i]=g[i+(n>>1)]*ifac[i]%mo;
	fo(i,(n>>1)+1,len-1) g[i]=0;
	fft(f,f,g);
}
int main()
{
	freopen("gift.in","r",stdin);
	//freopen("gift.out","w",stdout);
	n=read(),l=read(),r=read();
	fo(i,1,n) a[i]=read();
	fac[0]=1;
	fo(i,1,n) fac[i]=fac[i-1]*i%mo;
	ifac[n]=qmi(fac[n],mo-2);
	fd(i,n-1,0) ifac[i]=ifac[i+1]*(i+1)%mo;
	solve(l-1);
	fo(i,1,l-1) inc(b[l-1],a[i]*f[i]);
	//fo(i,1,l-1) printf("%lld ",(f[i]+mo)%mo);puts("");
	fo(i,l,r)
	{
		fd(j,i,1) f[j]=(f[j-1]-(i-1)*f[j])%mo;//Ss(n,m)=Ss(n-1,m-1)-(n-1)*Ss(n-1,m)
		if(i==1) f[0]=0;
		fo(j,1,i) inc(b[i],a[j]*f[j]);
	}
	fo(i,l,r) printf("%lld ",(b[i]-b[i-1]+mo+mo)%mo);
	return 0;
}

你可能感兴趣的:(FFT,NTT,FWT等线性变换)