音无结弦之时,天使跃动之心。立于浮华之世,奏响天籁之音。.|

次林梦叶

园龄:3年3个月粉丝:21关注:2

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 中国大陆许可协议进行许可。

posted @   次林梦叶  阅读(129)  评论(8编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起