2016 ACM/ICPC亚洲区青岛站现场赛(部分题解)

Posted wenzhixin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2016 ACM/ICPC亚洲区青岛站现场赛(部分题解)相关的知识,希望对你有一定的参考价值。

摘要

  本文主要列举并求解了2016 ACM/ICPC亚洲区青岛站现场赛的部分真题,着重介绍了各个题目的解题思路,结合详细的AC代码,意在熟悉青岛赛区的出题策略,以备战2018青岛站现场赛。


 

HDU 5984 Pocky

题意

  给出一根棒子(可以吃的)的长度x和切割过程中不能小于的长度d,每次随机的选取一个位置切开,吃掉左边的一半,对右边的棒子同样操作,直至剩余的长度不大于d时停止。现在给出x和d,问切割次数的数学期望是多少。

解题思路

  当看到第二个样例2 1时,结果是1.693147,联想到ln(2) = 0.693147,可猜测当x > d时,答案是ln(x/d) + 1。

详细解法:

  设长度为x、限制长度是d的棒切割次数的数学期望是f(x),首先当x < d时,f(x) = 0(直接结束,切割次数为0);当x >= d时,f(x) 应该是任选一点后,右边部分切割次数的数学期望加上1。设t是切割的位置,即技术分享图片,其中后面的式子表示切割点t的数学期望(积分0到x,取到这一点的概率乘上t的概率密度,也就是长度为t的切割次数的数学期望),进而又可以写成技术分享图片(积分中,系数可以自由进出),也即将f(x)写成如下形式

技术分享图片

技术分享图片

技术分享图片

   由此可得f(x) = ln(x) + c,当x = d时,f(d) = ln(d) + c = 1得,c = 1 - ln(d),代入f(x) = ln(x) - ln(d) + 1,也即f(x) = ln(x/d) + 1;

综上所述

技术分享图片

代码如下:

  其中涉及C语言中对数的表示方法,C中只定义两log(double x)和log10(double x),分别表示数学中的ln和lg,至于如何表示loga(b)呢?使用换底公式log(b)/log(a)即可。

 1 #include <cstdio>
 2 #include <cmath>
 3 
 4 int main()
 5 {
 6     double x, d;
 7     int T;
 8     scanf("%d", &T);
 9     while(T--) {
10         scanf("%lf%lf", &x, &d);
11         if(x <= d) 
12             printf("0.000000
");
13         else
14             printf("%.6lf
", log(x) - log(d) + 1);
15     }
16     return 0;
17 }

 HDU 5983 Pocket Cube

题意

  输入一个二阶魔方的状态,问能否一步将其复原。

解题思路

  需要细心和耐心,考虑每一种拧法,操作的时候,先顺时针改变一个面的数,然后改变四周的数,写出操作模板。要特别注意输入状态的次序,哪个面先,以及哪个角先。

代码如下:

  1 #include <cstdio>
  2 
  3 struct Magic2{
  4     int f[5], b[5], u[5], d[5], l[5], r[5];
  5     void get_u() {for(int i = 1 ; i <= 4; i++) {scanf("%d", &u[i]);}}
  6     void get_d() {for(int i = 1 ; i <= 4; i++) {scanf("%d", &d[i]);}}
  7     void get_f() {for(int i = 1 ; i <= 4; i++) {scanf("%d", &f[i]);}}
  8     void get_b() {for(int i = 1 ; i <= 4; i++) {scanf("%d", &b[i]);}}
  9     void get_l() {for(int i = 1 ; i <= 4; i++) {scanf("%d", &l[i]);}}
 10     void get_r() {for(int i = 1 ; i <= 4; i++) {scanf("%d", &r[i]);}}
 11     void L(int cnt) {
 12         for(; cnt > 0; cnt--) {
 13             int a[5];
 14             for(int i = 1; i <= 4; i++) a[i] = l[i];
 15             l[2] = a[1];l[1] = a[3];
 16             l[3] = a[4];l[4] = a[2];
 17 
 18             int x = b[3], y = b[1];
 19             b[3] = d[3], b[1] = d[1];
 20             d[3] = f[3], d[1] = f[1];
 21             f[3] = u[3], f[1] = u[1];
 22             u[3] = x, u[1] = y;
 23         }
 24     }
 25     void R(int cnt) {
 26         for(; cnt > 0; cnt--) {
 27             int a[5];
 28             for(int i = 1; i <= 4; i++) a[i] = r[i];
 29             r[1] = a[3], r[2] = a[1];
 30             r[3] = a[4], r[4] = a[2];
 31 
 32             int x = b[2], y = b[4];
 33             b[2] = u[2], b[4] = u[4];
 34             u[2] = f[2], u[4] = f[4];
 35             f[2] = d[2], f[4] = d[4];
 36             d[2] = x, d[4] = y;
 37         }
 38     }
 39     void U(int cnt) {
 40             for(; cnt > 0; cnt--) {
 41             int a[5];
 42             for(int i = 1; i <= 4; i++) a[i] = u[i];
 43             u[1] = a[3], u[2] = a[1];
 44             u[3] = a[4], u[4] = a[2];
 45 
 46             int x = b[3], y = b[4];
 47             b[3] = l[4], b[4] = l[2];
 48             l[4] = f[2], l[2] = f[1];
 49             f[2] = r[1], f[1] = r[3];
 50             r[1] = x, r[3] = y;
 51         }
 52     }
 53     void D(int cnt) {
 54         for(; cnt > 0; cnt--) {
 55             int a[5];
 56             for(int i = 1; i <= 4; i++) a[i] = d[i];
 57             d[2] = a[1], d[1] = a[3];
 58             d[4] = a[2], d[3] = a[4];
 59 
 60             int x = b[1], y = b[2];
 61             b[1] = r[4], b[2] = r[2];
 62             r[4] = f[3], r[2] = f[4];
 63             f[3] = l[1], f[4] = l[3];
 64             l[1] = x, l[3] = y;
 65         }
 66     }
 67     void F(int cnt) {
 68         for(; cnt > 0; cnt--) {
 69             int a[5];
 70             for(int i = 1; i <= 4; i++) a[i] = f[i];
 71             f[1] = a[3], f[2] = a[1];
 72             f[3] = a[4], f[4] = a[2];
 73 
 74             int x = u[3], y = u[4];
 75             u[3] = l[3], u[4] = l[4];
 76             l[3] = d[1], l[4] = d[2];
 77             d[1] = r[3], d[2] = r[4];
 78             r[3] = x, r[4] = y;
 79         }
 80     }
 81     void B(int cnt) {
 82         for(; cnt > 0; cnt--) {
 83             int a[5];
 84             for(int i = 1; i <= 4; i++) a[i] = u[i];
 85             u[1] = a[3], u[3] = a[4];
 86             u[2] = a[1], u[4] = a[2];
 87 
 88             int x = u[1], y = u[2];
 89             u[1] = r[1], u[2] = r[2];
 90             r[1] = d[4], r[2] = d[3];
 91             d[4] = l[1], d[3] = l[2];
 92             l[1] = x, l[2] = y;
 93         }
 94     }
 95     bool ok() {
 96         for(int i = 2; i <= 4; i++) {
 97             if(u[i] != u[1] || d[i] != d[1]
 98             || l[i] != l[1] || r[i] != r[1]
 99             || f[i] != f[1] || b[i] != b[1])
100                 return 0;
101         }
102         return 1;
103     }
104     bool operate(char ch) {
105         if(ch == u) {
106             U(1);
107             if(ok())
108                 return 1;
109             else {
110                 U(3);
111                 U(3);
112                 if(ok())
113                     return 1;
114                 else{
115                     U(1);
116                     return 0;
117                 }
118             }
119         }
120         if(ch == d) {
121             D(1);
122             if(ok())
123                 return 1;
124             else{
125                 D(3);
126                 D(3);
127                 if(ok())
128                     return 1;
129                 else{
130                     D(1);
131                     return 0;
132                 }
133             }
134         }
135         if(ch == f) {
136             F(1);
137             if(ok())
138                 return 1;
139             else{
140                 F(3);
141                 F(3);
142                 if(ok())
143                     return 1;
144                 else{
145                     F(1);
146                     return 0;
147                 }
148             }
149         }
150         if(ch == b) {
151             B(1);
152             if(ok())
153                 return 1;
154             else{
155                 B(3);
156                 B(3);
157                 if(ok())
158                     return 1;
159                 else{
160                     B(1);
161                     return 0;
162                 }
163             }
164         }
165         if(ch == l) {
166             L(1);
167             if(ok())
168                 return 1;
169             else{
170                 L(3);
171                 L(3);
172                 if(ok())
173                     return 1;
174                 else{
175                     L(1);
176                     return 0;
177                 }
178             }
179         }
180         if(ch == r) {
181             R(1);
182             if(ok())
183                 return 1;
184             else{
185                 R(3);
186                 R(3);
187                 if(ok())
188                     return 1;
189                 else{
190                     R(1);
191                     return 0;
192                 }
193             }
194         }
195     }
196     void print() {
197         puts("###");
198         for(int i = 1; i <= 4; i++) printf("%d ", u[i]); puts("");
199         for(int i = 1; i <= 4; i++) printf("%d ", f[i]); puts("");
200         for(int i = 1; i <= 4; i++) printf("%d ", d[i]); puts("");
201         for(int i = 1; i <= 4; i++) printf("%d ", b[i]); puts("");
202         for(int i = 1; i <= 4; i++) printf("%d ", l[i]); puts("");
203         for(int i = 1; i <= 4; i++) printf("%d ", r[i]); puts("");
204     }
205 }m2;
206 
207 int main()
208 {
209     int T;
210     scanf("%d", &T);
211     while(T--) {
212         m2.get_u();
213         m2.get_f();
214         m2.get_d();
215         m2.get_b();
216         m2.get_l();
217         m2.get_r();
218         if(m2.ok() || m2.operate(u) || m2.operate(d) || m2.operate(l)
219         || m2.operate(r) || m2.operate(f) || m2.operate(b))
220             printf("YES
");
221         else
222             printf("NO
");
223     }
224     return 0;
225 }

HDU 5985 Lucky Coins

题意

  给出n个硬币和每个硬币的数量和正面朝上的概率,问每个硬币成为幸运硬币的概率是多少。成为幸运硬币的条件是每投一次将所有背面朝上的硬币去掉,继续抛掷,直至剩下一种或者一个都剩下,那最后一种留下的硬币就是幸运硬币。

解题思路

  概率DP,我们定义dead[i][j]表示第i种硬币在前j步以内全部被抛弃的概率,显然技术分享图片

化简可得 技术分享图片.

  那么我们定义aliv[i][j] 表示第i种硬币在前j步以内至少有一个没有被抛弃的概率是 1 - dead[i][j],那么第i个硬币成为幸运硬币的概率大概等于(应为当k = 30的时候0.5的三十次方就很小)技术分享图片,其实际意义就是第i种硬币成为幸运硬币的概率等于模拟投掷100次,而每次让第1到n种硬币在k步全部被抛弃的概率乘上第i种硬币在第k步至少还有一个而第k+1步全部被抛弃的概率,当然前面的第1到第n种硬币全部被抛弃不包括第i种硬币,故完整的式子是:

技术分享图片

代码如下:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <cstring>
 5 
 6 using namespace std;
 7 
 8 const int maxn = 15;
 9 int n;
10 double num[maxn], p[maxn], ans[maxn];
11 double dead[maxn][110], alive[maxn][110];
12 
13 void cdead() {
14     for(int k = 1; k <= 100; k++) {
15         for(int i = 0; i < n; i++) {
16             dead[i][k] = pow(1.0 - pow(p[i], k), num[i]);
17         }
18     }
19 }
20 void calive() {
21     for(int k = 1; k <= 100; k++) {
22         for(int i = 0; i < n; i++) {
23             alive[i][k] = 1.0 - dead[i][k];
24         }
25     }
26 }
27 
28 int main()
29 {
30     int T;
31     scanf("%d", &T);
32     while(T--) {
33         scanf("%d", &n);
34         for(int i = 0; i < n; i++) {
35             scanf("%lf%lf", &num[i], &p[i]);
36         }
37         if(n == 1) {
38             printf("1.000000
");
39             continue;
40         }
41 
42         cdead();
43         calive();
44         memset(ans, 0, sizeof(ans));
45         for(int k = 1; k <= 100; k++) {
46             for(int i = 0; i < n; i++) {
47                 double tmp = 1;
48                 for(int j = 0; j < n; j++) {
49                     if(j == i)  continue;
50                     tmp *= dead[j][k];
51                 }
52                 ans[i] += tmp * (alive[i][k] - alive[i][k + 1]);
53             }
54         }
55 
56         for(int i = 0; i < n; i++) {
57             printf("%.6lf%c", ans[i], i == n - 1 ? 
 :  );
58         }
59     }
60     return 0;
61 }

   可以看出青岛站的题目还是有难度的,主要侧重的是数学推理,准备时应该多以数学推理为主,大战在即,加油!

以上是关于2016 ACM/ICPC亚洲区青岛站现场赛(部分题解)的主要内容,如果未能解决你的问题,请参考以下文章

2016ACM/ICPC亚洲区大连站现场赛题解报告

2016ACM/ICPC亚洲区大连站现场赛题解报告

2016ACM/ICPC亚洲区沈阳站现场赛题解报告

2016ACM/ICPC亚洲区沈阳站现场赛题解报告

2014ACM/ICPC亚洲区鞍山赛区现场赛题解报告

2016ACM/ICPC亚洲区青岛站 Coding Contest 费用流