2016 ACM-ICPC CHINA-Final
阿新 • • 發佈:2018-10-14
end 就是 有意思 algo 基本上 格子 pla -a string
題目鏈接:https://vjudge.net/contest/259560#overview
A題:簽到,略
B題:
C題:
D題:二分+貪心,主要是check函數怎麽寫的問題。我們采用貪心的策略,我們假設現在二分的值是mid,就是說能組成mid個tower,那麽,我們先選擇mid個最小的 balls,這個是最優的。因為如果我放著小的 ball 不選而去選大的,那麽下一層所要求的 ball 就更嚴格了。選取完 mid 個小的之後我們就可以再對每個小的選取剩下的最接近其2倍長度的球,為什麽選最接近的呢?道理和上面選小的 ball 是一樣的。這樣我們的貪心算法基本上就成型了。代碼如下:
1 #include <cstdio> 2View Code#include <algorithm> 3 using namespace std; 4 typedef long long LL; 5 const int maxn = 3e5 + 100; 6 int T; 7 int n, k; 8 9 LL a[maxn]; 10 int vis[maxn]; 11 12 13 bool check(int mid) 14 { 15 for (int i = 1; i <= n; i++) vis[i] = 0; 16 for (int i = 1; i <= mid; i++) vis[i] = 1; 17 18 int st = 1, ed = mid, flag = 0, maxx = ed; 19 for (int i = 1; i <= k-1; i++) 20 { 21 for (int j = st; j <= ed; j++) 22 if (vis[j]) 23 { 24 int pos = lower_bound(a+maxx+1,a+1+n,2*a[j])-a; 25 //printf("%d %d\n",mid, a[pos]);26 27 if (pos > n) { flag = 1; break; } 28 vis[pos] = 1; 29 maxx = max(maxx, pos); 30 } 31 if (flag) return false; 32 st = ed+1, ed = maxx; 33 } 34 35 return true; 36 } 37 38 39 int main(){ 40 scanf("%d",&T); 41 for(int t=1;t<=T;t++) 42 { 43 scanf("%d%d", &n, &k); 44 for (int i = 1; i <= n; i++) scanf("%lld", &a[i]); 45 sort(a+1, a+1+n); 46 47 int l = 0, r = n/k, ans = 0; 48 while(l <= r) 49 { 50 int mid = (l+r)/2; 51 if (check(mid)) 52 ans = mid, l = mid+1; 53 else r = mid-1; 54 } 55 56 printf("Case #%d: %d\n", t, ans); 57 } 58 return 0; 59 }
E題:簡單貪心,這個題雖說是簡答的貪心,但是過的人很少,因為這個題卡了精度,得使用 long double 才能過。
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 7 using namespace std; 8 const int maxn=100 + 10; 9 const int Max = 100000; 10 long double spend[maxn]; 11 12 int main(){ 13 int t; 14 scanf("%d", &t); 15 for (int ca = 1; ca <= t; ca++) 16 { 17 int n; 18 scanf("%d", &n); 19 for (int i = 1; i <= n; i++) 20 { 21 long double x, y; 22 char s; 23 cin >> x >> s >> y; 24 spend[i] = x/(y+x); 25 } 26 27 int ans = 0; 28 long double tot = 1; 29 sort(spend+1, spend+1+n); 30 31 for (int i = 1; i <= n; i++) 32 if (tot > spend[i]) tot -= spend[i], ans++; 33 34 printf("Case #%d: %d\n", ca, ans); 35 } 36 return 0; 37 }View Code
F題:
G題:
H題:思路,這個題一眼看上去就像一個 容斥 + dp 什麽的,當時覺得很復雜,就沒想了。賽後補題發現這個題目十分有意思。我們先來化簡一下這個式子:
第二步到第三步:實際上 g = 0 的 Ag 一直累加到 NM 這個過程就是 NM 的方格中任意放 K 個數的過程之和。所以就是:K^(NM)。
第三步到第四步:我們重新思考一下 Ag 是什麽,Ag 表示 有 g 個 great 值的填法總數之和,那麽 g*Ag 是不是就可以這樣理解,我們考慮每一個格子為 great 格,而其他位置我們不考慮。其他位置隨便填,統計有重復的情況正好是我們需要的,因為我們的 Ag 本來就要乘以 g。
代碼如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 const LL MOD = 1e9 + 7; 6 7 LL qpow(LL a, LL b) { 8 LL ans = 1; 9 while(b) { 10 if(b&1) ans = ans*a%MOD; 11 a = a*a%MOD; 12 b >>=1; 13 } 14 return ans; 15 } 16 17 int main() { 18 int T, ca = 1; 19 scanf("%d", &T); 20 while(T--) { 21 int N, M, K; 22 scanf("%d%d%d", &N, &M, &K); 23 LL ans = qpow(K, N*M); 24 for(int i = 1; i < K; ++i) 25 ans = (ans + qpow(i, N-1+M-1) * qpow(K, (N-1)*(M-1)) % MOD * N * M % MOD) % MOD; 26 if(N == 1 && M == 1) ans = (ans+1)%MOD; 27 printf("Case #%d: %lld\n", ca++, ans); 28 } 29 return 0; 30 }View Code
I 題:
J題:
K題:
L題:簽到,略
2016 ACM-ICPC CHINA-Final