P3382 【模板】三分法

提交 9.62k
通过 5.68k
时间限制 100ms
内存限制 125.00MB
题目提供者 HansBug
历史分数100

提交记录

标签

暂无标签
进入讨论版

相关讨论

 
查看讨论

推荐题目

 
查看推荐
 

展开

题目描述

如题,给出一个 NNN 次函数,保证在范围 [l,r][l, r][l,r] 内存在一点 xxx,使得 [l,x][l, x][l,x] 上单调增,[x,r][x, r][x,r] 上单调减。试求出 xxx 的值。

输入格式

第一行一次包含一个正整数 NNN 和两个实数 l,rl, rl,r,含义如题目描述所示。

第二行包含 N+1N + 1N+1 个实数,从高到低依次表示该 NNN 次函数各项的系数。

输出格式

输出为一行,包含一个实数,即为 xxx 的值。四舍五入保留 555 位小数。

输入输出样例

输入 #1
3 -0.9981 0.5
1 -3 -3 1
输出 #1
-0.41421

说明/提示

对于 100%100\%100% 的数据,7≤N≤137 \le N \le 137N13。

【样例解释】

如图所示,红色段即为该函数 f(x)=x3−3x2−3x+1f(x) = x^3 - 3 x^2 - 3x + 1f(x)=x33x23x+1 在区间 [−0.9981,0.5][-0.9981, 0.5][0.9981,0.5] 上的图像。

x=−0.41421x = -0.41421x=0.41421 时图像位于最高点,故此时函数在 [l,x][l, x][l,x] 上单调增,[x,r][x, r][x,r] 上单调减,故 x=−0.41421x = -0.41421x=0.41421,输出 −0.41421-0.414210.41421。

(Tip.l&r的范围并不是非常大ww不会超过一位数)

 

思路:

  求单峰极值可以想到模拟退火三分,和二分类比一下,二分需要一个中间点,三分需要两个中间点,就是三等分点然后根据求的是极大值还是极小值比较三分点并转移

CODE

 

 1 #include <bits/stdc++.h>
 2 #define dbg(x) cout << #x << "=" << x << endl
 3 #define eps 1e-8
 4 
 5 using namespace std;
 6 typedef long long LL;
 7 
 8 template<class T>inline void read(T &res)
 9 {
10     char c;T flag=1;
11     while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
12     while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
13 }
14 
15 namespace _buff {
16     const size_t BUFF = 1 << 19;
17     char ibuf[BUFF], *ib = ibuf, *ie = ibuf;
18     char getc() {
19         if (ib == ie) {
20             ib = ibuf;
21             ie = ibuf + fread(ibuf, 1, BUFF, stdin);
22         }
23         return ib == ie ? -1 : *ib++;
24     }
25 }
26 
27 int qread() {
28     using namespace _buff;
29     int ret = 0;
30     bool pos = true;
31     char c = getc();
32     for (; (c < '0' || c > '9') && c != '-'; c = getc()) {
33         assert(~c);
34     }
35     if (c == '-') {
36         pos = false;
37         c = getc();
38     }
39     for (; c >= '0' && c <= '9'; c = getc()) {
40         ret = (ret << 3) + (ret << 1) + (c ^ 48);
41     }
42     return pos ? ret : -ret;
43 }
44 
45 int n;
46 double l,r;
47 double a[20];
48 
49 double f(double x) {//函数计算
50     double u = 1, p = 0;
51     for(int i = n; i >= 0; --i) {
52         p += u*a[i];
53         u *= x;
54     }
55     return p;
56 }
57 
58 double ts(double l, double r) {
59     while(l + eps < r) {
60         double lmid = l + (r-l)/3, rmid = r - (r-l)/3;
61         if(f(lmid) <= f(rmid)) {
62             l = lmid;
63         }
64         else {
65             r = rmid;
66         }
67     }
68     return r;
69 }
70 
71 int main()
72 {
73     memset(a, 0, sizeof(a));
74     scanf("%d",&n);
75     scanf("%lf%lf",&l, &r);
76 
77     for(int i = 0; i <= n; ++i) {
78         scanf("%lf", &a[i]);
79     }
80     printf("%.5f\n",ts(l,r));
81     return 0;
82 }
View Code

 

 1 #include <bits/stdc++.h>
 2 #define dbg(x) cout << #x << "=" << x << endl
 3 #define eps 1e-8
 4 
 5 using namespace std;
 6 typedef long long LL;
 7 
 8 template<class T>inline void read(T &res)
 9 {
10     char c;T flag=1;
11     while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
12     while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
13 }
14 
15 namespace _buff {
16     const size_t BUFF = 1 << 19;
17     char ibuf[BUFF], *ib = ibuf, *ie = ibuf;
18     char getc() {
19         if (ib == ie) {
20             ib = ibuf;
21             ie = ibuf + fread(ibuf, 1, BUFF, stdin);
22         }
23         return ib == ie ? -1 : *ib++;
24     }
25 }
26 
27 int qread() {
28     using namespace _buff;
29     int ret = 0;
30     bool pos = true;
31     char c = getc();
32     for (; (c < '0' || c > '9') && c != '-'; c = getc()) {
33         assert(~c);
34     }
35     if (c == '-') {
36         pos = false;
37         c = getc();
38     }
39     for (; c >= '0' && c <= '9'; c = getc()) {
40         ret = (ret << 3) + (ret << 1) + (c ^ 48);
41     }
42     return pos ? ret : -ret;
43 }
44 
45 int n;
46 double l,r;
47 double a[20];
48 
49 double f(double x) {///多项式求值秦九韶算法把2n+1次乘法n次加法简化为n次乘法和n次加法
50     double u = 1, p = 0;
51     for(int i = n; i >= 0; --i) {
52         p += u*a[i];
53         u *= x;
54     }
55     return p;
56 }
57 
58 double ts(double l, double r) {
59     while(l + eps < r) {
60         double lmid = l + (r-l)/3, rmid = r - (r-l)/3;
61         if(f(lmid) <= f(rmid)) {
62             l = lmid;
63         }
64         else {
65             r = rmid;
66         }
67     }
68     return r;
69 }
70 
71 int main()
72 {
73     memset(a, 0, sizeof(a));
74     scanf("%d",&n);
75     scanf("%lf%lf",&l, &r);
76 
77     for(int i = 0; i <= n; ++i) {
78         scanf("%lf", &a[i]);
79     }
80     printf("%.5f\n",ts(l,r));
81     return 0;
8