14909: [Sdoi2017]龙与地下城

#include <cmath>
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
#define eps 1e-7
const int N=(1<<19)+5;
const double PI=acos(-1),K=1.0/sqrt(2*PI);

int rev[N];
struct Com//plex
{
	double x,y;
	Com() {}
	Com(double x,double y):x(x),y(y) {}
	Com operator +(const Com &a) {return Com(x+a.x, y+a.y);}
	Com operator -(const Com &a) {return Com(x-a.x, y-a.y);}
	Com operator *(const Com &a) {return Com(x*a.x-y*a.y, x*a.y+y*a.x);}
}A[N];

inline int read()
{
	int now=0;register char c=gc();
	for(;!isdigit(c);c=gc());
	for(;isdigit(c);now=now*10+c-'0',c=gc());
	return now;
}
Com FP(Com x,int k)
{
	Com t(1,0);
	for(; k; k>>=1,x=x*x)
		if(k&1) t=t*x;
	return t;
}
void FFT(Com *a,int lim,int opt)
{
	for(int i=1; i<lim; ++i) if(i<rev[i]) std::swap(a[i],a[rev[i]]);
	for(int i=2; i<=lim; i<<=1)
	{
		int mid=i>>1;
		Com Wn(cos(PI/mid),opt*sin(PI/mid)),t;
		for(int j=0; j<lim; j+=i)
		{
			Com w(1,0);
			for(int k=0; k<mid; ++k,w=w*Wn)
				a[j+k+mid]=a[j+k]-(t=a[j+k+mid]*w),
				a[j+k]=a[j+k]+t;
		}
	}
	if(opt==-1) for(int i=0; i<lim; ++i) a[i].x/=lim;
}
inline double F(double x)
{
	return K*exp(-x*x*0.5);
}
inline double Simpson(double l,double r)
{
	return (r-l)*(F(l)+F(r)+4*F((l+r)*0.5))/6.0;
}
double Int(double l,double r,double Eps,double ans)
{
	double m=(l+r)*0.5,lans=Simpson(l,m),rans=Simpson(m,r);
	if(fabs(lans+rans-ans)<Eps) return lans+rans;
	return Int(l,m,Eps*0.5,lans)+Int(m,r,Eps*0.5,rans);
}

int main()
{
	for(int T=read(),X,Y,lim; T--; )
	{
		X=read(),Y=read(),lim=X*Y;
		int len=0;
		while(1<<len<=lim) ++len; lim=1<<len;
		if(lim<N)
		{
			--len;
			for(int i=0; i<lim; ++i) A[i]=Com(0,0),rev[i]=(rev[i>>1]>>1)|((i&1)<<len);
			double xx=1.0/X,ans;
			for(int i=0; i<X; ++i) A[i].x=xx;
			FFT(A,lim,1);
			for(int i=0; i<lim; ++i) A[i]=FP(A[i],Y);
			FFT(A,lim,-1);
			for(int i=1,l,r; i<=10; ++i)
			{
				l=read(),r=read(),ans=0;
				for(int j=l; j<=r; ++j) ans+=A[j].x;
				printf("%.7lf\n",ans);
			}
		}
		else
		{
			double l,r,mu=1.0*(X-1)/2,sigma=1.0*(X*X-1)/12/*\sigma^2*/,a=mu*Y,b=sqrt(sigma*Y);
			for(int i=1; i<=10; ++i)
				l=1.0*(read()-a)/b, r=1.0*(read()-a)/b,
				printf("%.7lf\n",Int(0,r,eps,Simpson(0,r))-Int(0,l,eps,Simpson(0,l)));
//				printf("%.7lf\n",Int(l,r,eps,Simpson(l,r)));//WA
		}
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值