辛普森积分

simpson积分公式

∫ a b f ( x )   d x ≈ b − a 6 [ f ( a ) + 4 f ( a + b 2 ) + f ( b ) ] \int_{a}^{b}f(x)\,dx\approx\frac{b-a}{6}[f(a)+4f(\frac{a+b}{2})+f(b)] abf(x)dx6ba[f(a)+4f(2a+b)+f(b)]

他实质上就是用二次函数来拟合我们的函数
推导过程:
g ( x ) = A x 2 + B x + C g(x)=Ax^2+Bx+C g(x)=Ax2+Bx+C
G ( x ) = A x 3 3 + B x 2 2 + C x + D G(x)=\frac{Ax^3}{3}+\frac{Bx^2}{2}+Cx+D G(x)=3Ax3+2Bx2+Cx+D
∫ a b f ( x )   d x = ∫ a b g ( x ) d x \int_{a}^{b}f(x)\,dx=\int_{a}^{b}g(x)dx abf(x)dx=abg(x)dx
= G ( b ) − G ( a ) =G(b)-G(a) =G(b)G(a)
= A b 3 3 + B b 2 2 + C b − A a 3 3 − B a 2 2 − C a =\frac{Ab^3}{3}+\frac{Bb^2}{2}+Cb-\frac{Aa^3}{3}-\frac{Ba^2}{2}-Ca =3Ab3+2Bb2+Cb3Aa32Ba2Ca
= A 3 ( b − a ) ( a 2 + a b + b 2 ) + B 2 ( b − a ) ( b + a ) + C ( b − a ) =\frac{A}{3}(b-a)(a^2+ab+b^2)+\frac{B}{2}(b-a)(b+a)+C(b-a) =3A(ba)(a2+ab+b2)+2B(ba)(b+a)+C(ba)
= b − a 6 ( 2 A a 2 + 2 A a b + 2 A b 2 + 3 B b + 3 B a + 6 C ) =\frac{b-a}{6}(2Aa^2+2Aab+2Ab^2+3Bb+3Ba+6C) =6ba(2Aa2+2Aab+2Ab2+3Bb+3Ba+6C)
= b − a 6 ( A a 2 + B a + C + A b 2 + B b + C + ( A a 2 + 2 A a b + A b 2 + 2 B b + 2 B a + 4 C ) ) =\frac{b-a}{6}(Aa^2+Ba+C+Ab^2+Bb+C+(Aa^2+2Aab+Ab^2+2Bb+2Ba+4C)) =6ba(Aa2+Ba+C+Ab2+Bb+C+(Aa2+2Aab+Ab2+2Bb+2Ba+4C))
= b − a 6 ( A a 2 + B a + C + A b 2 + B b + C + 4 ( A ( a + b 2 ) 2 + B ( a + b 2 ) + C ) ) =\frac{b-a}{6}(Aa^2+Ba+C+Ab^2+Bb+C+4(A(\frac{a+b}{2})^2+B(\frac{a+b}{2})+C)) =6ba(Aa2+Ba+C+Ab2+Bb+C+4(A(2a+b)2+B(2a+b)+C))
= b − a 6 ( g ( a ) + g ( b ) + 4 g ( a + b 2 ) ) =\frac{b-a}{6}(g(a)+g(b)+4g(\frac{a+b}{2})) =6ba(g(a)+g(b)+4g(2a+b))
我们在用simpson时用f函数去替代g函数即可
【模板】自适应辛普森法1

#include<bits/stdc++.h>
#define db double
using namespace std;
db a,b,c,d,l,r;
db f(db x){return (c*x+d)/(a*x+b);}
db calc(db l,db mid,db r){return (r-l)*(f(l)+4*f(mid)+f(r))/6;}
db simpson(db l,db r,db eps,db val){
	db mid=(l+r)/2.0;	
	db lmid=(l+mid)/2,rmid=(mid+r)/2;
	db vall=calc(l,lmid,mid),valr=calc(mid,rmid,r);
	if (fabs(vall+valr-val)<=eps) return val; else 
	return simpson(l,mid,eps/2.0,vall)+simpson(mid,r,eps/2.0,valr);
}
int main(){
	scanf("%lf%lf%lf%lf%lf%lf",&a,&b,&c,&d,&l,&r);
	printf("%.6lf\n",simpson(l,r,1e-7,calc(l,(l+r)/2,r)));
}

圆的面积并

#pragma GCC optimize (3,"inline","Ofast")
#include<bits/stdc++.h>
#define db double
using namespace std;
const int MAXN=1010;
const db eps=1e-13;
struct cir{
    db x,y,r;
}o[MAXN],tmp[MAXN];
pair<db,db>po[MAXN];
int n,st,ed;
db xl[MAXN],xr[MAXN];
bool cmp(cir x,cir y)
{
    return x.r>y.r;
}
bool cmp2(cir x,cir y)
{
    return x.x-x.r<y.x-y.r;
}
double sqr(double x)
{
    return x*x;
}
double dis(cir x,cir y)
{
    sqr(x.x-y.x)+sqr(x.y-y.y);
}
bool pan(cir x,cir y)
{
    dis(x,y)<=sqr(x.r-y.r);
}
void cut()
{
    sort(o+1,o+n+1,cmp);
    int k=0,j;
    for (int i=1;i<=n;i++)
    {
        for (j=1;j<=k;j++)
        if (pan(o[i],tmp[j]))
         {
            break;
         }
        if (j>k) tmp[++k]=o[i];
    }
    n=k;
    for (int i=1;i<=n;i++) o[i]=tmp[i];
}
db get(db x)
{
    int tot=0;
    for (int i=st;i<=ed;i++)
    {
        if (xl[i]>=x||xr[i]<=x) continue;
        db dis=sqrt(o[i].r-sqr(x-o[i].x));
        po[++tot]=make_pair(o[i].y-dis,o[i].y+dis);
    }
    sort(po+1,po+tot+1);
    int j;
    db ans=0;
    for (int i=1;i<=tot;i++)
    {
        db l=po[i].first,r=po[i].second;
        for (j=i+1;j<=tot;j++)
         if (po[j].first<=r) r=max(r,po[j].second);
         else break;
        ans+=r-l;
        i=j-1;
    }
    return ans;
}
db calc(db x,db fl,db fmid,db fr) {return x/6.0*(fl+fmid*4+fr);}
db simpson(db l,db mid,db r,db fl,db fmid,db fr,db s)
{
    db mid1=(l+mid)/2,mid2=(mid+r)/2;
    db t1=get(mid1),t2=get(mid2);
    db g1=calc(mid-l,fl,t1,fmid),g2=calc(r-mid,fmid,t2,fr);
    if (fabs(g1+g2-s)<eps) return g1+g2;
    return simpson(l,mid1,mid,fl,t1,fmid,g1)+simpson(mid,mid2,r,fmid,t2,fr,g2);
}
void solve()
{
    cut();
    sort(o+1,o+n+1,cmp2);
    for (int i=1;i<=n;i++) xl[i]=o[i].x-o[i].r,xr[i]=o[i].x+o[i].r,o[i].r=sqr(o[i].r);
    int j;
    db ans=0;
    for (int i=1;i<=n;i++)
    {
        db l=xl[i],r=xr[i];
        for (j=i+1;j<=n;j++)
         if (xl[j]>r) break;
         else
         {
            r=max(r,xr[j]);
         }
        db mid=(l+r)/2;
        st=i; ed=j-1; i=j-1;
        db fl=get(l),fmid=get(mid),fr=get(r);
        ans+=simpson(l,mid,r,fl,fmid,fr,calc(r-l,fl,fmid,fr));
    }
    printf("%.3lf",ans);
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%lf%lf%lf",&o[i].x,&o[i].y,&o[i].r);
    }
    solve();
}

题目描述

小Q终于回家了。他开始了他最喜欢的Qazor之旅。Qazor的等离子场对过近的或过远的目标没有效果。小Q同时在多个位置释放了等离子场。他想知道他的等离子场能覆盖多大的面积。
输入
第一行一个整数n,表示等离子场的数量。
接下来n行,每行四个整数x,y,R,r,分别表示等离子场的横坐标,纵坐标,影响范围的上界,影响范围的下界。
输出
一行一个实数,保留三位小数,表示等离子场覆盖的面积。
样例输入
2
-1 0 2 1
1 0 2 1
样例输出
16.742
数据规模与约定
对于10%的数据,n=1
对于20%的数据,n<=2
对于40%的数据,n<=50
对于另外10%的数据,x=0,y=0
对于另外20%的数据,r=0
对于100%的数据,n<=200,|x|,|y|,|R|,|r|<=10000
时间限制 1s
内存限制 256M

#include<bits/stdc++.h>
#define db double
#define mk(x,y) make_pair(x,y)	
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1010;
struct node{
	int x,y,R,r;
};
pair<db,int>c[N];
node v[N];
int n;
bool cmp(pair<db,int> x,pair<db,int> y){
	return x.first<y.first;
}
db sqr(db x){
	return x*x;
} 
db get(db x){
	int len=0;
	for (int i=1;i<=n;i++) {
	if (x>v[i].x-v[i].R&&x<v[i].x+v[i].R) {
		db d=sqrt(sqr(v[i].R)-sqr(v[i].x-x));
		c[++len]=mk(v[i].y-d,1); c[++len]=mk(v[i].y+d,-1);
	}
	if (x>v[i].x-v[i].r&&x<v[i].x+v[i].r) {
		db d=sqrt(sqr(v[i].r)-sqr(v[i].x-x));
		c[++len]=mk(v[i].y-d,-1); c[++len]=mk(v[i].y+d,1);
	} 
	}
	sort(c+1,c+len+1,cmp);
	int sum=1;
	db ans=0;
	for (int i=2;i<=len;i++) {
	if (sum) ans+=c[i].first-c[i-1].first;
	sum+=c[i].second;
	}
	return ans;
}
db calc(db l,db mid,db r){return (r-l)*(get(l)+4*get(mid)+get(r))/6;}
db simpson(db l,db r,db eps,db val){
	db mid=(l+r)/2;
	db lmid=(l+mid)/2,rmid=(mid+r)/2;
	db vall=calc(l,lmid,mid),valr=calc(mid,rmid,r);
	if (fabs(vall+valr-val)<eps) return val;
	else return simpson(l,mid,eps,vall)+simpson(mid,r,eps,valr); 
}
int main(){
	scanf("%d",&n);
	int lmin=inf,lmax=-inf;
	for (int i=1;i<=n;i++){
		scanf("%d%d%d%d",&v[i].x,&v[i].y,&v[i].R,&v[i].r);
		lmin=min(lmin,v[i].x-v[i].R); lmax=max(lmax,v[i].x+v[i].R); 
	}
	printf("%.3lf\n",simpson(lmin,lmax,1e-7,calc(1.0*lmin,1.0*(lmin+lmax)/2,1.0*lmax)));
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值