朴素积分
\int_L^R\frac{cx+d}{ax+b}\mathrm{d}x
#include <bits/stdc++.h>
using namespace std;
typedef double db;
typedef db func(db);
db a, b, c, d, L, R;
db f(db x) {
return (c * x + d) / (a * x + b);
}
db simpson(db l, db r, func f) {
db mid = (l + r) / 2;
return (f(l) + 4 * f(mid) + f(r)) * (r - l) / 6;
}
db asr(db l, db r, db eps, db A, func f) {
db mid = (l + r) / 2;
db L = simpson(l, mid, f), R = simpson(mid, r, f);
if (fabs(L + R - A) <= 15 * eps) return L + R + (L + R - A) / 15;
return asr(l, mid, eps / 2, L, f) + asr(mid, r, eps / 2, R, f);
}
db asr(db l, db r, db eps) {
return asr(l, r, eps, simpson(l, r, f), f);
}
int main() {
cin >> a >> b >> c >> d >> L >> R;
printf("%.6lf\n", asr(L, R, 1e-6));
return 0;
}
高精度积分(分段)
#include <bits/stdc++.h>
using namespace std;
typedef long double db;
typedef db func(db);
db a, b, c, d, L, R;
db f(db x) {
return (c * x + d) / (a * x + b);
}
db simpson(db l, db r, func f) {
db mid = (l + r) / 2;
return (f(l) + 4 * f(mid) + f(r)) * (r - l) / 6;
}
db asr(db l, db r, db eps, db A, func f) {
db mid = (l + r) / 2;
db L = simpson(l, mid, f), R = simpson(mid, r, f);
if (fabs(L + R - A) <= 15 * eps) return L + R + (L + R - A) / 15;
return asr(l, mid, eps / 2, L, f) + asr(mid, r, eps / 2, R, f);
}
db asr(db l, db r, db eps, func f, int x = 5) {
db dx = (r - l) / x, ret = 0;
for (db i = l; i < r - eps; i += dx) {
ret += asr(i, i + dx, eps, simpson(i, i + dx, f), f);
}
return ret;
}
双重积分
例题:gym101987G Secret Code(2019ICPC 首尔)
题目大意:
有 A,B,C 三个人要见面,每个人在 [0,S] 随机选择一个时间点作为见面时间,先到的那个人要等下一个人来了之后和他确认信息,然后马上就走。例如,假如 A 先到,B 其次,C 最后到,那么 A 要等 B 到了之后和B确认完信息,然后 A 走,B 再等 C 到了和 C 确认完信息,这样任务就完成了。
现给出 A,B,C 三人的最长等待时间 wa,wb,wc,求任务能完成的概率。
解题思路:
首先,A 到的时间可以是 [0, S];B 到的时间是 [A, \min(A+wa,S)];C 可以在 [B, \min(B+wb, S)] 到。因此我们枚举 3 个人来的顺序,答案为:
\frac{1}{S^3}\cdot \int_0^{S}\left(\int_A^{\min(A+wa,S)}\left(\min(B+wb,S)-B\right)\mathrm{d}B\right)\mathrm{d}A
#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-9;
int S, wa, wb, wc, w[3];
typedef long double db;
typedef db func(db);
db simpson(db l, db r, func f) {
db mid = (l + r) / 2;
return (f(l) + 4 * f(mid) + f(r)) * (r - l) / 6;
}
db asr(db l, db r, db eps, db A, func f) {
db mid = (l + r) / 2;
db L = simpson(l, mid, f), R = simpson(mid, r, f);
if (fabs(L + R - A) <= 15 * eps) return L + R + (L + R - A) / 15;
return asr(l, mid, eps / 2, L, f) + asr(mid, r, eps / 2, R, f);
}
db asr(db l, db r, db eps, func f) {
db dx = (r - l) / 5, ret = 0;
for (db i = l; i < r - eps; i += dx) {
ret += asr(i, i + dx, eps, simpson(i, i + dx, f), f);
}
return ret;
}
db f(db x) {
return min(x + w[1], (db)S) - x;
}
db g(db x) {
return asr(x, min(x + w[0], (db)S), eps, f);
}
db work() {
return asr(0.0, (db)S, eps, g);
}
int n;
bool equ(db a, db b) {
return fabs(a - b) < 1e-10;
}
struct Data {
db ans;
int i;
bool operator < (const whnb &x) const {
return equ(ans, x.ans) ? i < x.i : ans < x.ans;
}
};
vector< Data > rec;
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d %d %d %d", &S, &wa, &wb, &wc);
double ans = 0;
w[0] = wa, w[1] = wb, w[2] = wc; ans += work();
w[0] = wa, w[1] = wc, w[2] = wb; ans += work();
w[0] = wb, w[1] = wa, w[2] = wc; ans += work();
w[0] = wb, w[1] = wc, w[2] = wa; ans += work();
w[0] = wc, w[1] = wa, w[2] = wb; ans += work();
w[0] = wc, w[1] = wb, w[2] = wa; ans += work();
ans /= 1.0 * S * S * S;
rec.push_back({ans, i});
}
sort(rec.begin(), rec.end());
for (auto x : rec) printf("%d ", x.i); puts("");
return 0;
}