1. 程式人生 > >2016 ACM/ICPC亞洲區青島站現場賽(部分題解)

2016 ACM/ICPC亞洲區青島站現場賽(部分題解)

多少 條件 技術 留下 tin tdi scanf .get max

摘要

  本文主要列舉並求解了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\n"); 13 else 14 printf("%.6lf\n", 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\n");
221         else
222             printf("NO\n");
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\n");
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 ? \n :  );
58         }
59     }
60     return 0;
61 }

  可以看出青島站的題目還是有難度的,主要側重的是數學推理,準備時應該多以數學推理為主,大戰在即,加油!

2016 ACM/ICPC亞洲區青島站現場賽(部分題解)