2016-2017 ACM-ICPC CHINA-Final Solution
Problem A. Number Theory Problem
Solved.
水。
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 const int maxn = 1e5 + 10; 6 7 typedef long long ll; 8 9 int n; 10 ll arr[maxn], ans[maxn]; 11 12 void Init() 13 { 14 arr[0] = 1; 15 for(int i = 1; i <= maxn; ++i)View Code16 { 17 arr[i] = (arr[i - 1] * 2) % 7; 18 ans[i] = ans[i - 1]; 19 if(arr[i] == 1) ans[i]++; 20 } 21 } 22 23 int main() 24 { 25 Init(); 26 int t; 27 scanf("%d",&t); 28 for(int cas = 1; cas <= t; ++cas) 29 { 30 scanf("%d", &n);31 printf("Case #%d: %lld\n", cas, ans[n]); 32 } 33 return 0; 34 }
Problem B. Hemi Palindrome
Unsolved.
題意:
定義$Hemi Palindrome$ 為去掉所有奇數位上的數字後是迴文串或者去掉所有偶數位上的數是迴文串,給出一個長度$N$
構造一個字典序最小的$Hemi Palindrome$
Problem C. Mr. Panda and Strips
Upsolved.
題意:
選擇序列中兩段不相交的連續區間,要求這兩段區間並沒有重複數字,求最長長度。
思路:
雙指標列舉第一個區間,然後再左段和右段再雙指標列舉最長的合併區間
我們考慮雙指標擴充套件右指標的過程中,也可以更新答案
但是對於已經在前一個左指標上擴充套件過的,就沒有必要擴充套件了。
.....L......R........
我們考慮列舉的時候是這樣的
那麼L.......R 這一段沒有必要再檢查是否有更大的答案,因為如果有,那麼必然是L - 1........R 是更大的
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 1010 5 #define M 100010 6 int t, n, a[N]; 7 int vis[M][2]; 8 9 int solve(int ql, int qr) 10 { 11 int res = 0; 12 for (int i = ql, r = ql - 1; i <= qr; ++i) 13 { 14 if (r < i) r = i - 1; 15 while (r < qr && !vis[a[r + 1]][0] && !vis[a[r + 1]][1]) 16 { 17 ++r; 18 vis[a[r]][1] = 1; 19 } 20 res = max(res, r - i + 1); 21 vis[a[i]][1] = 0; 22 } 23 return res; 24 } 25 26 int main() 27 { 28 scanf("%d", &t); 29 for (int kase = 1; kase <= t; ++kase) 30 { 31 printf("Case #%d: ", kase); 32 scanf("%d", &n); 33 for (int i = 1; i <= n; ++i) scanf("%d", a + i); 34 memset(vis, 0, sizeof vis); 35 int res = 0; 36 for (int i = 1, r = 0; i <= n; ++i) 37 { 38 while (r < n && !vis[a[r + 1]][0]) 39 { 40 ++r; 41 vis[a[r]][0] = 1; 42 res = max(res, r - i + 1 + max(solve(1, i - 1), solve(r + 1, n))); 43 } 44 int tmp = max(solve(1, i - 1), solve(r + 1, n)); 45 res = max(res, r - i + 1 + tmp); 46 vis[a[i]][0] = 0; 47 } 48 printf("%d\n", res); 49 } 50 return 0; 51 }View Code
Problem D. Ice Cream Tower
Solved.
題意:
要構造一個冰激凌塔,並且要求$第i層的尺寸需要 >= 第 i - 1 層的尺寸 \cdot 2$
給出n個冰激凌的尺寸,求最多構造多少個K層的塔
思路:
二分答案,貪心擺放。
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 typedef long long ll; 6 const int maxn = 3e5 + 10; 7 8 int n, k; 9 ll arr[maxn]; 10 ll tower[maxn]; 11 12 bool check(int mid) 13 { 14 int now = 1; 15 for(int i = 1; i <= mid; ++i) tower[i] = arr[now++]; 16 for(int i = mid + 1; i <= mid * k; ++i) 17 { 18 while(now <= n && arr[now] < tower[i - mid] * 2) ++now; 19 if(now > n) return false; 20 tower[i] = arr[now++]; 21 } 22 return true; 23 } 24 25 int main() 26 { 27 int t; 28 scanf("%d", &t); 29 for(int cas = 1; cas <= t; ++cas) 30 { 31 scanf("%d %d", &n, &k); 32 for(int i = 1; i <= n; ++i) scanf("%lld", arr + i); 33 sort(arr + 1, arr + 1 + n); 34 int l = 0, r = n / k, res = 0; 35 while(r - l >= 0) 36 { 37 int mid = (l + r) >> 1; 38 if(check(mid)) 39 { 40 l = mid + 1; 41 res = mid; 42 } 43 else r = mid - 1; 44 } 45 printf("Case #%d: %d\n", cas, res); 46 } 47 return 0; 48 }View Code
Problem E. Bet
Solved.
題意:
有一家賭球公司,你要賭球,對於每一支隊伍 賠率是$A_i : B_i$
你要如何下注,使得如果有一隻球隊贏了,你就不會虧本,求你最多能下注的數量。
思路:
假設本金為1, 考慮對$第i支球隊下注p_i 那麼需要滿足 p_i + p_i \cdot \frac{B_i}{A_i} > 1 $
移項之後即為$p_i > \frac{A_i}{A_i + B_i}$
那麼對所有球隊按這個式子從小到大排序,取到大於一就不取了
注意精度問題,資料保證小數點後最多三位,直接$ * 1000$
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 typedef long long ll; 6 7 const double eps = 1e-8; 8 const ll MOD = 1e9 + 7; 9 const ll INFLL = 0x3f3f3f3f3f3f3f3f; 10 const int INF = 0x3f3f3f3f; 11 const int maxn = 1e5 + 10; 12 13 int n; 14 long double arr[maxn]; 15 16 void RUN() 17 { 18 int t; 19 scanf("%d", &t); 20 for (int cas = 1; cas <= t; ++cas) 21 { 22 scanf("%d", &n); 23 for (int i = 1; i <= n; ++i) 24 { 25 long double ai, bi; 26 scanf("%Lf:%Lf", &ai, &bi); 27 ai = (int)(ai * 1000 + 0.1); 28 bi = (int)(bi * 1000 + 0.2); 29 arr[i] = ai / (ai + bi); 30 } 31 sort(arr + 1, arr + 1 + n); 32 long double sum = 0; 33 int cnt = 0; 34 for (int i = 1; i <= n; ++i) 35 { 36 sum += arr[i]; 37 if (sum >= (long double)1.0) break; 38 cnt++; 39 } 40 printf("Case #%d: %d\n", cas, cnt); 41 } 42 } 43 44 int main() 45 { 46 #ifdef LOCAL_JUDGE 47 freopen("Text.txt", "r", stdin); 48 #endif // LOCAL_JUDGE 49 50 RUN(); 51 52 #ifdef LOCAL_JUDGE 53 fclose(stdin); 54 #endif // LOCAL_JUDGE 55 56 return 0; 57 }View Code
Problem F. Mr. Panda and Fantastic Beasts
Unsolved.
Problem G. Pandaria
Unsolved.
Problem H. Great Cells
Solved.
題意:
定義$Ag 矩陣中恰好有g個好點的方案數,定義好點為那一個點所在的行和列它最大,嚴格最大$
求$\sum_{i = 0}^{i = n * m} (g + 1) * A_g$
思路:
考慮將式子拆成
$\sum_{g = 0}^{g = n * m} g * A_g + \sum_{g = 0}^{g = n * m}A_g$
顯然 右邊的項的答案就是$k^{n * m}$
再考慮左邊
如果我把式子 除以$\sum_{g = 1}^{g = n * m} A_g$
那麼整個式子表達的含義即$g$ 的數學期望
我們再考慮用另一種方法求數學期望
$E \cdot \sum_{g = 1}^{g = n * m} A_g = n * m * \sum_{i = 2}^{i = k} (i - 1) ^ {n + m - 2} \cdot k ^{(n - 1) * (m - 1)}$
含義是 令$i為好點的值,有多少種方案,那麼顯然,任意一個點都可以是好點,那麼同行同列的取值為[1, i - 1]$
$其它格子的取值隨意$
那麼等式右邊算出來的即是$所有g的總和$
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 typedef long long ll; 6 7 const ll MOD = 1e9 + 7; 8 9 ll qpow(ll x, ll n) 10 { 11 ll res = 1; 12 while(n) 13 { 14 if(n & 1) res = res * x % MOD; 15 x = x * x % MOD; 16 n >>= 1; 17 } 18 return res; 19 } 20 21 int t; 22 int n, m, k; 23 24 int main() 25 { 26 scanf("%d", &t); 27 for(int cas = 1; cas <= t; ++cas) 28 { 29 scanf("%d %d %d", &n, &m, &k); 30 ll ans = 0; 31 for(int i = 2; i <= k; ++i) 32 { 33 ans = (ans + n * m % MOD * qpow(i - 1, n + m - 2) % MOD * qpow(k, (n - 1) * (m - 1)) % MOD) % MOD; 34 } 35 ans = (ans + qpow(k, n * m)) % MOD; 36 printf("Case #%d: %lld\n", cas, ans); 37 } 38 return 0; 39 }View Code
Problem I. Cherry Pick
Unsolved.
Problem J. Mr.Panda and TubeMaster
Unsolved.
Problem K. Justice Rains From Above
Unsolved.
Problem L. World Cup
Solved.
水。
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 int arr[3] = {3, 1, 0}; 6 int brr[3] = {0, 1, 3}; 7 int ans[10][10][10][10]; 8 9 void Init() 10 { 11 for(int i1 = 0; i1 < 3; ++i1) 12 { 13 for(int i2 = 0; i2 < 3; ++i2) 14 { 15 for(int i3 = 0; i3 < 3; ++i3) 16 { 17 for(int i4 = 0; i4 < 3; ++i4) 18 { 19 for(int i5 = 0; i5 < 3; ++i5) 20 { 21 for(int i6 = 0; i6 < 3; ++i6) 22 { 23 int a = arr[i1] + arr[i2] + arr[i3]; 24 int b = brr[i1] + arr[i4] + arr[i5]; 25 int c = brr[i2] + brr[i4] + arr[i6]; 26 int d = brr[i3] + brr[i5] + brr[i6]; 27 ans[a][b][c][d]++; 28 } 29 } 30 } 31 } 32 } 33 } 34 } 35 36 int a, b, c, d; 37 38 int main() 39 { 40 Init(); 41 int t; 42 scanf("%d", &t); 43 for(int cas = 1; cas <= t; ++cas) 44 { 45 scanf("%d %d %d %d",&a, &b, &c, &d); 46 printf("Case #%d: ", cas); 47 if(a > 9 || b > 9 || c > 9 || d > 9) puts("Wrong Scoreboard"); 48 else if(ans[a][b][c][d] > 1) puts("No"); 49 else if(ans[a][b][c][d]) puts("Yes"); 50 else puts("Wrong Scoreboard"); 51 } 52 return 0; 53 }View Code