1. 程式人生 > >2016 ACM-ICPC CHINA-Final

2016 ACM-ICPC CHINA-Final

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>
 2
#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 }
View Code

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