AtCoder Beginner Contest 279
《D - Freefall》
二分,三分
二分写法
其实可以算出T=x*b+a/sqrt(x+1);
然后让我们求T的最小值,因为很容易看出这个函数是大概如图
,其实就是对T求导,然后找到让T’=0的x(二分找,因为这个时候导函数的图形是单调的),因为要求的是整数x,所以可能二分出来的x有偏差,要扩大范围求
1 #include <iostream>
2 #include <algorithm>
3 #include <cstring>
4 #include <cmath>
5 using namespace std;
6 typedef long long ll;
7 ll a, b;
8 int main()
9 {
10 cin >> a >> b;
11 ll x = pow((double(a) / double(2 * b)), double(2) / 3) - 1;
12 ll l = x - 10, r = x + 10;
13 double ans = 1e20;
14 for (; l <= r; l++)
15 {
16 double t = double(l) * double(b) + double(a) / sqrt(double(l + 1));
17 ans = min(ans, t);
18 }
19 printf("%.10lf", ans);
20 return 0;
21 }
三分写法
在做题的时候我毫无脑子地直接二分,但是忘记了
参考博客:https://zhuanlan.zhihu.com/p/100617613
这个博客中讲了浮点数三分,我这里是整数三分
1 #include <iostream>
2 #include <algorithm>
3 #include <cstring>
4 #include <cmath>
5 using namespace std;
6 typedef long long ll;
7 ll a, b;
8 double f(ll x)
9 {
10 return double(x) * double(b) + double(a) / sqrt(double(x + 1));
11 }
12 int main()
13 {
14 cin >> a >> b;
15 ll l = 0, r = a / b + 1;
16 while (r - l > 2)
17 {
18 ll m1 = (l * 2 + r) / 3;
19 ll m2 = (l + r * 2) / 3;
20 if (f(m1) > f(m2))
21 l = m1;
22 else
23 r = m2;
24 }
25 double ans = a;
26 for (ll i = l; i <= r; i++)
27 {
28 ans = min(ans, f(i));
29 }
30 printf("%.10lf", ans);
31 return 0;
32 }
《E - Cheating Amidakuji》
思维
本题的题意即是给出序列A=(A1,A2,........,Am),B=(1,2,......,n);
按照i=1,......,m,对于每个i,对B进行k=1,2,..........,i-1,i+1,.............,m;swap(B(Ak),B(Ak+1))的交换操作。
求:对于每一个i,找到交换后的序列中B(j)=1中的j
解:
定义Ci为对B进行了k=1,2,......,i-1,i+1,....,m;swap(B(Ak),B(Ak+1))交换操作后的序列
定义C0对B进行了k=1,2,......,i-1,i,i+1,....,m;swap(B(Ak),B(Ak+1))交换操作后的序列
明显:在只对B序列交换到k=1,2,3,....,i-1时,Ci序列==C0序列
然后k=i,Ci不进行交换,C0进行交换,这个是导致Ci序列与C0序列不同的原因
那么我们就对k=i时进行分析:
设Cs定义为对B序列交换到k=1,2,3,....,i-1时的序列,设x=B(Ai),y=B(Ai+1),这两个数正是当k=i时要进行交换的
假设Cs序列如下:(_表示数)
Cs:_ _ _ _ _ _ _ _ _ x,y _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
然后对Cs进行交换K=i,达到如下序列:
_ _ _ _ _ _ _ _ _ y,x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
对于C0来说,到达 _ _ _ _ _ _ _ _ _ y,x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 这个状态后变要进行K=i+1,.....,m时的交换
对于Ci来说,到达 _ _ _ _ _ _ _ _ _ x,y _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 这个状态后变要进行K=i+1,.....,m时的交换
不管K=i+1,.....,m时的交换是否会涉及到x,y,都有下面条件成立:
对于1<=j<=n
(C0)j!=x && (C0)j!=y 时有 (C0)j=(Ci)j
(C0)j==x,时有(Ci)j=y
(C0)j==y 时有 (Ci)j=x
为啥会这样,因为
对于C0,Ci两个序列来说,只是将x,y反过来再进行后面的排序了,
即如果C0为: _ _ _ _ y_ _ _ _ _ x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ,那么必然Ci为 _ _ _ _ x_ _ _ _ _ y _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
其余地方的数都是相等的
那这个条件对于我们解题有啥用?
1.当x!=1 && y!=1,输出C0序列中数为1的下标
2.当x==1 ,输出C0序列中数为y的下标
3.当y==1,输出C0序列中数为x的下标
1 #include <iostream>
2 #include <algorithm>
3 #include <cstring>
4 #include <vector>
5 using namespace std;
6 const int N = 2 * 1e5 + 1;
7 int a[N], n, m;
8 // numtoC0[i]表示数i在C0[]中的下标为numtoC0[i];
9 int C0[N], numtoC0[N];
10 int main()
11 {
12 cin >> n >> m;
13 for (int i = 1; i <= m; i++)
14 scanf("%d", &a[i]);
15 for (int i = 1; i <= n; i++)
16 C0[i] = i;
17 // 搞出C0;
18 for (int i = 1; i <= m; i++)
19 {
20 // 要交换数组中p1与p2下标中的数;
21 int p1 = a[i], p2 = a[i] + 1;
22 int t = C0[p1];
23 C0[p1] = C0[p2], C0[p2] = t;
24 }
25
26 /* for (int i = 1; i <= n; i++)
27 cout << C0[i] << " ";
28 cout << endl; */
29
30 for (int i = 1; i <= n; i++)
31 numtoC0[C0[i]] = i;
32 int Cs[N];
33 for (int i = 1; i <= n; i++)
34 Cs[i] = i;
35 for (int i = 1; i <= m; i++)
36 {
37 // 每次Cs[]都表示正好交换到i-1的序列
38 if (i - 1 > 0)
39 {
40 int p1 = a[i - 1], p2 = a[i - 1] + 1;
41 int t = Cs[p1];
42 Cs[p1] = Cs[p2], Cs[p2] = t;
43 }
44
45 /* for (int i = 1; i <= n; i++)
46 cout << Cs[i] << " ";
47 cout << endl; */
48
49 int p1 = a[i], p2 = a[i] + 1;
50 if (Cs[p1] != 1 && Cs[p2] != 1)
51 cout << numtoC0[1] << endl;
52 else if (Cs[p1] == 1)
53 cout << numtoC0[Cs[p2]] << endl;
54 else if (Cs[p2] == 1)
55 cout << numtoC0[Cs[p1]] << endl;
56 }
57 return 0;
58 }
本文作者:次林梦叶
本文链接:https://www.cnblogs.com/cilinmengye/p/16930297.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步