zoukankan      html  css  js  c++  java
  • 2016 ACM-ICPC CHINA-Final

    题目链接: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
    ",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
    ", 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
    ", 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
    ", ca++, ans);
    28     }
    29     return 0;
    30 }
    View Code

    I 题:

    J题:

    K题:

    L题:签到,略

  • 相关阅读:
    【HAOI2014】贴海报
    【HAOI2016】食物链
    【NOI2003】银河英雄传
    【HAOI2013】花卉节
    【BZOJ1702】[usaco2007margold]队列平衡
    【网络流24】餐巾
    洛谷 [P1265] 公路修建
    全排列与 康托展开
    洛谷 [P1403] 约数研究
    高精度模板
  • 原文地址:https://www.cnblogs.com/DynastySun/p/9754188.html
Copyright © 2011-2022 走看看