2019.03.25【洛谷P5265】【模板】多项式反三角函数(多项式开方)

版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/88807751

传送门


解析:

好像三角函数还可以用于求某些交错序列的生成函数,但是反三角函数我是真的不知道这TM有什么用了。

直接上公式,证明用隐函数求导可以做。

arcsin ( x ) = 1 1 x 2 arccos ( x ) = 1 1 x 2 arctan ( x ) = 1 1 + x 2 \arcsin^\prime(x)=\frac{1}{\sqrt{1-x^2}}\\\arccos^\prime(x)=-\frac{1}{\sqrt{1-x^2}}\\\arctan^\prime(x)=\frac{1}{1+x^2}

现在我们要求

F ( x ) = arcsin ( A ( x ) ) F ( x ) = A ( x ) 1 A 2 ( x ) F ( x ) = A ( x ) 1 A 2 ( x ) d x F(x)=\arcsin(A(x))\\ F^\prime(x)=\frac{A^\prime (x)}{\sqrt{1-A^2(x)}}\\ F(x)=\int\frac{A^\prime(x)}{\sqrt{1-A^2(x)}}dx


F ( x ) = arctan ( A ( x ) ) F ( x ) = A ( x ) 1 + A 2 ( x ) F ( x ) = A ( x ) 1 + A 2 ( x ) d x F(x)=\arctan(A(x))\\ F^\prime(x)=\frac{A^\prime(x)}{1+A^2(x)}\\ F(x)=\int\frac{A^\prime(x)}{1+A^2(x)}dx

把板子拉一拉就行了。


代码:

#include<bits/stdc++.h>
#define ll long long
#define re register
#define gc get_char
#define cs const

namespace IO{
	inline char get_char(){
		static cs int Rlen=1<<20|1;
		static char buf[Rlen],*p1,*p2;
		return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++; 
	}
	
	inline int getint(){
		re char c;
		while(!isdigit(c=gc()));re int num=c^48;
		while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
		return num;
	}
}
using namespace IO;

using std::cerr;
using std::cout;
using std::swap; 

cs int mod=998244353;
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(int a,int b){return a<b?a-b+mod:a-b;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline int quickpow(int a,int b,int res=1){
	while(b){
		if(b&1)res=mul(res,a);
		a=mul(a,a);
		b>>=1;
	}
	return res;
}

cs int N=1<<19|7;

int inv[N];
inline void init_inv(){
	inv[0]=inv[1]=1;
	for(int re i=2;i<N;++i)inv[i]=mul(inv[mod%i],mod-mod/i);
}

namespace POLY{
	typedef std::vector<int> Poly;
	
	inline void print(cs Poly &a,char c=' ',std::ostream &out=cout){
		for(int re i=0;i<a.size();++i)out<<a[i]<<c;
	}
	
	int r[N],invl;
	inline void NTT(Poly &A,int len,int typ){
		if(typ==-1)reverse(A.begin()+1,A.begin()+len);
		for(int re i=0;i<len;++i)if(i<r[i])swap(A[i],A[r[i]]);
		for(int re i=1;i<len;i<<=1){
			int wn=quickpow(3,(mod-1)/i/2);
			for(int re j=0;j<len;j+=i<<1)
			for(int re k=0,x,y,w=1;k<i;++k,w=mul(w,wn)){
				x=A[j+k],y=mul(A[j+k+i],w);
				A[j+k]=add(x,y);
				A[j+k+i]=dec(x,y);
			}
		}
		if(typ==-1)for(int re i=0;i<len;++i)A[i]=mul(A[i],invl);
	}
	inline void init_rev(int len){
		invl=quickpow(len,mod-2);
		for(int re i=0;i<len;++i)r[i]=r[i>>1]>>1|((i&1)*(len>>1));
	}
	
	inline Poly Deriv(Poly a){
		for(int re i=0;i+1<a.size();++i)a[i]=mul(a[i+1],i+1);
		a.pop_back();
		return a;
	}
	inline Poly Integ(Poly a){
		a.push_back(0);
		for(int re i=a.size()-1;i;--i)a[i]=mul(a[i-1],inv[i]);
		a[0]=0;
		return a;
	}
	
	inline Poly operator*(Poly a,Poly b){
		int deg=a.size()+b.size()-1,l=1;
		while(l<deg)l<<=1;
		init_rev(l);
		a.resize(l),NTT(a,l,1);
		b.resize(l),NTT(b,l,1);
		for(int re i=0;i<l;++i)a[i]=mul(a[i],b[i]);
		NTT(a,l,-1),a.resize(deg);
		return a; 
	}
	
	inline Poly Inv(cs Poly &a,int lim){
		Poly c,b(1,quickpow(a[0],mod-2));
		for(int re l=4;(l>>2)<lim;l<<=1){
			c=a;c.resize(l>>1);
			init_rev(l);
			c.resize(l),NTT(c,l,1);
			b.resize(l),NTT(b,l,1);
			for(int re i=0;i<l;++i)b[i]=mul(b[i],dec(2,mul(b[i],c[i])));
			NTT(b,l,-1),b.resize(l>>1);
		}
		b.resize(lim);
		return b;
	}
	inline Poly Inv(cs Poly &a){return Inv(a,a.size());}
	
	inline Poly Sqrt(cs Poly &a,int lim){
		Poly c,b(1,1);
		for(int re l=4;(l>>2)<lim;l<<=1){
			init_rev(l);
			c=a,c.resize(l>>1);
			b.resize(l>>1);
			c=c*Inv(b);
			for(int re i=0;i<(l>>1);++i)b[i]=mul(add(b[i],c[i]),inv[2]);
		}
		b.resize(lim);
		return b;
	}
	inline Poly Sqrt(cs Poly &a){return Sqrt(a,a.size());}
	
	inline Poly arcsin(Poly a,int lim){
		Poly b=Deriv(a);
		a=a*a,a.resize(lim);
		a[0]=dec(1,a[0]);
		for(int re i=1;i<a.size();++i)a[i]=dec(0,a[i]);
		a=Integ(Inv(Sqrt(a))*b);
		a.resize(lim);
		return a;
	}
	inline Poly arcsin(cs Poly &a){return arcsin(a,a.size());}
	
	inline Poly arctan(Poly a,int lim){
		Poly b=Deriv(a); 
		a=a*a,a.resize(lim);
		a[0]=add(a[0],1);
		a=Integ(Inv(a)*b);
		a.resize(lim);
		return a;
	}
	inline Poly arctan(cs Poly &a){return arctan(a,a.size());}
}
using namespace POLY;

Poly a;
int typ;
signed main(){
	init_inv();
	a.resize(getint()),typ=getint();
	for(int re i=0;i<a.size();++i)a[i]=getint();
	print(typ?arctan(a):arcsin(a));
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zxyoi_dreamer/article/details/88807751