zoukankan      html  css  js  c++  java
  • 2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018) Solution

    A. Altruistic Amphibians

    Upsolved.

    题意:

    $有n只青蛙,其属性用三元组表示 <l_i, w_i, h_i> l_i是它能跳的高度,w_i是它的体重,h_i是它的身高$

    一只青蛙的承重不能超过它的体重,它可以踩在别的青蛙上面跳

    一口井的深度为$d, 一只青蛙能够跳出去当且仅当它离井口的距离严格小于它的l_i$

    $离井口的距离为d - 它所踩的青蛙的身高和,当然可以不踩其他青蛙$

    求最多跳出去多少只青蛙

    思路:

    显然,重量最大的青蛙肯定只能在最下面

    那么按重量大小排个序

    然后考虑递推到下面

    $dp[i] 表示 重量为i的青蛙最高能处在什么样的高度$

    $dp[j - a[i].w] = dp[j] +a[i].h ;;j in [a[i].w, 2 * a[i].w)$

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define ll long long
     5 #define N 100010
     6 const int D = (int)1e8 + 10;
     7 int n, d;
     8 struct node
     9 {
    10     int l, w, h;
    11     void scan() { scanf("%d%d%d", &l, &w, &h); }
    12     bool operator < (const node &r) const { return w > r.w; }
    13 }a[N];
    14 int dp[D];
    15 
    16 int main()
    17 {
    18     while (scanf("%d%d", &n, &d) != EOF)
    19     {
    20         for (int i = 1; i <= n; ++i) a[i].scan();
    21         sort(a + 1, a + 1 + n);
    22         int res = 0;
    23         for (int i = 1; i <= n; ++i)
    24         {
    25             if (dp[a[i].w] + a[i].l > d) ++res;
    26             for (int j = a[i].w; j < min(2 * a[i].w, (int)1e8 + 2); ++j)
    27                 dp[j - a[i].w] = max(dp[j - a[i].w], dp[j] + a[i].h);
    28         }
    29         printf("%d
    ", res); 
    30     }
    31     return 0;
    32 }
    View Code

    B. Baby Bites

    Solved.

    签到。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 int n;
     5 int pre, now;
     6 string s;
     7 
     8 int f()
     9 {
    10     if (s == "mumble") return -1;
    11     int res = 0;
    12     for (int i = 0, len = s.size(); i < len; ++i) res = res * 10 + s[i] - '0';
    13     return res;
    14 }
    15 
    16 bool solve()
    17 {
    18     bool flag = 1;
    19     pre = 0;
    20     for (int i = 1; i <= n; ++i)
    21     {
    22         cin >> s;
    23         now = f();
    24         if (now == -1) ++pre;
    25         else if (now != pre + 1) flag = 0;
    26         else pre = now;
    27     }
    28     return flag;
    29 }
    30 
    31 int main()
    32 {
    33     ios::sync_with_stdio(false);
    34     cin.tie(0); cout.tie(0);
    35     while (cin >> n) cout << (solve() ? "makes sense" : "something is fishy") << "
    ";
    36     return 0;
    37 }
    View Code

    C. Code Cleanups

    Solved.

    签到。

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 int n;
     6 int vis[400];
     7 
     8 int main()
     9 {
    10     while(~scanf("%d", &n))
    11     {
    12         memset(vis, 0, sizeof vis);
    13         for(int i = 1, num; i <= n; ++i)
    14         {
    15             scanf("%d", &num);
    16             vis[num]++;
    17         }
    18         int ans = 0;
    19         int tmp = 0;
    20         int pre = 0;
    21         for(int i = 1; i <= 365; ++i)
    22         {
    23             tmp += vis[i];
    24             pre += tmp;
    25             if(pre >= 20) 
    26             {
    27                 ++ans;
    28                 pre = 0;
    29                 tmp = 0;
    30             }
    31         }
    32         if(pre) ans++;
    33         printf("%d
    ", ans);
    34     }
    35     return 0;
    36 }
    View Code

    D. Delivery Delays

    Upsolved.

    题意:

    有一张无向图,顶点1有一家披萨店,时不时会有一点发布订单表示它在$s_i时刻要一份披萨,这份披萨要在t_i时刻才能好$

    $只有一个送货员,必须满足先到先服务的原则,如何安排送货流程使得等待时间最长的顾客的等待时间最短$

    思路:

    先预处理出任意两点之间的最短路径,再考虑二分答案

    $用dp验证$

    $dp[i][j][k] 表示已经送完前i个点,拿到前j个披萨,k in [0, 1]$

    $0 表示 目前处于第i个点,1表示目前处于披萨店$

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 
      4 #define ll long long
      5 #define N 1010
      6 #define INFLL 0x3f3f3f3f3f3f3f3f
      7 struct Graph
      8 {
      9     struct node
     10     {
     11         int to, nx, w;
     12         node () {}
     13         node (int to, int nx, int w) : to(to), nx(nx), w(w) {}
     14     }a[N << 5];
     15     int head[N], pos;
     16     void init()
     17     {
     18         memset(head, -1, sizeof head);
     19         pos = 0;
     20     }
     21     void add(int u, int v, int w)
     22     {
     23         a[++pos] = node(v, head[u], w); head[u] = pos;
     24         a[++pos] = node(u, head[v], w); head[v] = pos; 
     25     }
     26 }G;
     27 #define erp(u) for (int it = G.head[u], v = G.a[it].to, w = G.a[it].w; ~it; it = G.a[it].nx, v = G.a[it].to, w = G.a[it].w)
     28 
     29 int n, m, q;
     30 ll dist[N][N];
     31 namespace Dij
     32 {
     33     struct node
     34     {
     35         int to; ll w;
     36         node () {}
     37         node (int to, ll w) : to(to), w(w) {}
     38         bool operator < (const node &r) const { return w > r.w; }
     39     };
     40     bool used[N];
     41     void run()
     42     {
     43         for (int st = 1; st <= n; ++st)
     44         {
     45             for (int i = 1; i <= n; ++i) dist[st][i] = INFLL, used[i] = false;
     46             priority_queue <node> q; q.emplace(st, 0); dist[st][st] = 0;
     47             while (!q.empty())
     48             {
     49                 int u = q.top().to; q.pop();
     50                 if (used[u]) continue;
     51                 used[u] = 1;
     52                 erp(u) if (!used[v] && dist[st][v] > dist[st][u] + w)
     53                 {
     54                     dist[st][v] = dist[st][u] + w;
     55                     q.emplace(v, dist[st][v]);
     56                 }
     57             }
     58         }
     59     }
     60 }
     61 
     62 ll dp[N][N][2]; 
     63 // dp[i][j][0] 表示已经送完前i个点,拿到前j个披萨,目前处于第i个点的最小时间
     64 // dp[i][j][1] 表示已经送完前i个点,拿到前j个披萨,目前处于披萨店的最小时间
     65 int s[N], u[N], t[N];
     66 bool check(ll x)
     67 {
     68     memset(dp, 0x3f, sizeof dp);
     69     dp[0][0][1] = 0; 
     70     for (int i = 0; i < q; ++i)
     71     {
     72         for (int j = i; j <= q; ++j)
     73         {
     74             for (int o = 0; o < 2; ++o)
     75             {
     76                 if (!o)
     77                 {
     78                     dp[i][j][1] = min(dp[i][j][1], dp[i][j][0] + 1ll * dist[u[i]][1]);
     79                     if (j > i)
     80                     {
     81                         ll T = dp[i][j][0] + dist[u[i]][u[i + 1]];
     82                         if (s[i + 1] + x >= T)
     83                             dp[i + 1][j][0] = min(dp[i + 1][j][0], T);
     84                     }
     85                 }
     86                 else
     87                 {
     88                     if (j < q)
     89                        dp[i][j + 1][1] = min(dp[i][j + 1][1], max(dp[i][j][1], 1ll * t[j + 1]));
     90                     if (j > i) 
     91                     {
     92                         ll T = dp[i][j][1] + dist[1][u[i + 1]];
     93                         if (s[i + 1] + x >= T)
     94                             dp[i + 1][j][0] = min(dp[i + 1][j][0], T);
     95                     }
     96                 }
     97             }
     98         }
     99     }
    100     return dp[q][q][0] != INFLL;
    101 }
    102 
    103 int main()
    104 {
    105     while (scanf("%d%d", &n, &m) != EOF)
    106     {
    107         G.init();
    108         for (int i = 1, u, v, w; i <= m; ++i)
    109         {
    110             scanf("%d%d%d", &u, &v, &w);
    111             G.add(u, v, w);
    112         }
    113         Dij::run(); 
    114         scanf("%d", &q);
    115         for (int i = 1; i <= q; ++i) scanf("%d%d%d", s + i, u + i, t + i); 
    116         ll l = 0, r = INFLL, res = -1;
    117         while (r - l >= 0)
    118         {
    119             ll mid = (l + r) >> 1;
    120             if (check(mid))
    121             {
    122                 res = mid;
    123                 r = mid - 1;
    124             }
    125             else
    126                 l = mid + 1;
    127         }
    128         printf("%lld
    ", res);
    129     }
    130     return 0;
    131 }
    View Code

    E. Explosion Exploit

    Solved.

    题意:

    你有$n个随从,对方有m个随从,你现在可以发动一个技能,造成d点伤害$

    $每点伤害都会等概率的下落到敌方的随从身上,求发动一次技能,敌方随从全部死亡的概率$

    思路:

    概率记忆化搜索

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 typedef long long ll;
     6 
     7 int n, m, d;
     8 int sum[3][10];
     9 map <ll, double>dp;
    10 
    11 ll calc()
    12 {
    13     ll res = 0;
    14     for(int i = 1; i <= 6; ++i)
    15     {
    16         res += sum[0][i];
    17         res *= 10;
    18     }
    19     for(int i = 1; i <= 6; ++i)
    20     {
    21         res += sum[1][i];
    22         res *= 10;
    23     }
    24     return res;
    25 }
    26 
    27 double DFS(ll S, int limit)
    28 {
    29     if(dp.count(S)) return dp[S];
    30     int cnt = 0;
    31     for(int i = 1; i <= 6; ++i) cnt += sum[1][i];
    32     if(!cnt) return 1;
    33     if(limit == 0) return 0;
    34     for(int i = 1; i <= 6; ++i) cnt += sum[0][i];
    35     double res = 0;
    36     for(int i = 0; i < 2; ++i)
    37     {
    38         for(int j = 1; j <= 6; ++j)
    39         {
    40             if(sum[i][j] == 0) continue;
    41             sum[i][j]--;
    42             sum[i][j - 1]++;
    43             double tmp = DFS(calc(), limit - 1);
    44             sum[i][j]++;
    45             sum[i][j - 1]--;
    46             res += 1.0 * sum[i][j] / cnt * tmp;
    47         }
    48     }
    49     dp[S] = res;
    50     return res;
    51 }
    52 
    53 int main()
    54 {
    55     while(~scanf("%d %d %d", &n, &m, &d))
    56     {
    57         dp.clear();
    58         memset(sum, 0, sizeof sum);
    59         for(int i = 1, num; i <= n; ++i)
    60         {
    61             scanf("%d", &num);
    62             sum[0][num]++;
    63         }
    64         for(int i = 1, num; i <= m; ++i)
    65         {
    66             scanf("%d", &num);
    67             sum[1][num]++;
    68         }
    69         double ans = DFS(calc(), d);
    70         printf("%.10f
    ", ans);
    71     }
    72     return 0;
    73 }
    View Code

    F. Firing the Phaser

    Unsolved.

    G. Game Scheduling

    Unsolved.

    H. House Lawn

    Solved.

    题意:

    有一些割草机,工作一段时间,休息一段时间

    求哪些机器在T周至少割草T次,如果有,按输入顺序输出价格最低的

    思路:

    因为$周期是LCM(t + r, 10080), 如果这个周期内是可以的,那就是可以的$

    因为如果中间有一周割不完了,那么后面肯定是割不完的

    因为开始的局面相当于满电让你割,那么对于后面的情况

    每周平均割草的次数肯定小于等于前面的

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define N 110
     5 #define ll long long
     6 
     7 ll l; int m;
     8 ll Min;
     9 
    10 ll gcd(ll a, ll b)
    11 {
    12     return b == 0 ? a : gcd(b,  a % b);
    13 }
    14 
    15 ll lcm(ll a, ll b)
    16 {
    17     return a * b / gcd(a, b);
    18 }
    19 
    20 struct qnode
    21 {
    22     string name;
    23     ll p, c, t, r;
    24     bool flag;
    25     void scan()
    26     {
    27         flag = false;
    28         p = 0, c = 0, t = 0, r = 0;
    29         name = "";
    30         string s;
    31         getline(cin, s); 
    32         int i, len = s.size();
    33         for (i = 0; s[i] != ','; ++i)
    34             name += s[i];
    35         for (++i; s[i] != ','; ++i) p = p * 10 + s[i] - '0';
    36         for (++i; s[i] != ','; ++i) c = c * 10 + s[i] - '0';
    37         for (++i; s[i] != ','; ++i) t = t * 10 + s[i] - '0';
    38         for (++i; i < len; ++i) r = r * 10 + s[i] - '0';
    39         //cout << p << " " << c << " " << t << " " << r << endl;
    40     }
    41     void f()
    42     {
    43         ll need = l % (c * t) == 0 ? l / (c * t) : l / (c * t) + 1;
    44         ll remind = 0; 
    45         if (l % (c * t)) remind = t - (l - (c * t) * (need)) % c; 
    46         ll tot = need * (t + r);
    47         tot -= remind; 
    48         flag = tot <= 10080;
    49         if (flag) Min = min(Min, p);
    50     }
    51     void F4()
    52     {
    53         flag = false;
    54         ll circle = lcm(t + r, 10080);
    55         ll T = circle / 10080;
    56         if(circle / (t + r) * c * t>= T * l)
    57         {
    58             flag = true;
    59             Min = min(Min, p);
    60         }
    61     }
    62 }qarr[N];
    63 
    64 int main()
    65 {
    66     ios::sync_with_stdio(false);
    67     cin.tie(0); cout.tie(0); 
    68     while (cin >> l >> m)
    69     {
    70         string s;
    71         getline(cin, s); 
    72         Min = 0x3f3f3f3f3f3f3f3f;
    73         for (int i = 1; i <= m; ++i) qarr[i].scan(), qarr[i].F4();
    74         vector <string> res;
    75         for (int i = 1; i <= m; ++i) if (qarr[i].flag && qarr[i].p == Min) res.push_back(qarr[i].name);
    76         for (auto it : res) cout << it << "
    ";
    77         if (res.empty()) cout << "no such mower
    ";
    78     }
    79     return 0;
    80 }
    View Code

    I. Intergalactic Bidding

    Solved.

    简单模拟。

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 
      4 #define N 1010
      5 #define DLEN 4
      6 #define MAXN 9999
      7 int n;
      8 
      9 class BigNum
     10 {
     11 private:
     12         int a[N];
     13         int len;
     14 public:
     15         BigNum() { len = 1; memset(a, 0, sizeof a); }
     16         BigNum(const char *s)
     17         {
     18             int t, k, index, L, i;
     19             memset(a, 0, sizeof a);
     20             L = strlen(s);
     21             len = L / DLEN;
     22             if (L % DLEN) ++len;
     23             index = 0;
     24             for (int i = L - 1; i >= 0; i -= DLEN)
     25             {
     26                 t = 0;
     27                 k = i - DLEN + 1;
     28                 if (k < 0) k = 0;
     29                 for (int j = k; j <= i; ++j)
     30                     t = t * 10 + s[j] - '0';
     31                 a[index++] = t;  
     32             }
     33         }
     34         bool operator == (const BigNum &T) const
     35         {
     36             if (len != T.len) return false;
     37             for (int i = 0; i < len; ++i) if (a[i] != T.a[i])
     38                 return false;
     39             return true;
     40         }
     41         bool operator < (const BigNum &T) const
     42         {
     43             if (len != T.len) return len < T.len;
     44             for (int i = len - 1; i >= 0; --i) if (a[i] != T.a[i])
     45                 return a[i] < T.a[i];
     46             return true; 
     47         }
     48         BigNum& operator = (const BigNum &n)
     49         {
     50             int i;
     51             len = n.len;
     52             memset(a, 0, sizeof a);
     53             for (int i = 0; i < len; ++i) a[i] = n.a[i];
     54             return *this;
     55         }
     56         BigNum operator - (const BigNum &T) const
     57         {
     58             int i, j, big;
     59             BigNum t1, t2;
     60             t1 = *this, t2 = T;
     61             big = t1.len;
     62             for (i = 0; i < big; ++i) 
     63             {
     64             
     65                 if (t1.a[i] < t2.a[i])
     66                 {
     67                     j = i + 1;
     68                     while (t1.a[j] == 0) ++j;
     69                     t1.a[j--]--;
     70                     while (j > i) t1.a[j--] += MAXN;
     71                     t1.a[i] += MAXN + 1 - t2.a[i];         
     72                 }
     73                 else t1.a[i] -= t2.a[i]; 
     74             }
     75             t1.len = big;
     76             while (t1.a[t1.len - 1] == 0 && t1.len > 1)
     77             {
     78                 t1.len--;
     79                 big--;
     80             }
     81             return t1;
     82         }
     83         void print()
     84         {
     85             cout << a[len - 1];
     86             for (int i = len - 2; i >= 0; --i) 
     87                 printf("%04d", a[i]);
     88             puts("");
     89         }
     90 };
     91 
     92 char str[N]; 
     93 BigNum s; 
     94 
     95 struct node
     96 {
     97     string name; 
     98     BigNum val;
     99     void scan()
    100     {
    101         cin >> name;
    102         cin >> str;
    103         val = BigNum(str); 
    104     }
    105     bool operator < (const node &r) { return r.val < val; } 
    106 }arr[N];
    107 
    108 vector <string> res;
    109 int main()
    110 {
    111     ios::sync_with_stdio(false);
    112     cin.tie(0); cout.tie(0);
    113     while (cin >> n)
    114     {
    115         res.clear();
    116         cin >> str; s = BigNum(str);
    117         for (int i = 1; i <= n; ++i) arr[i].scan();
    118         sort(arr + 1, arr + 1 + n);
    119         for (int i = 1; i <= n; ++i) if (arr[i].val < s)
    120         {
    121             s = s - arr[i].val;
    122             res.push_back(arr[i].name);
    123         }
    124         if (!(s == BigNum("0"))) cout << "0
    ";
    125         else 
    126         {
    127             cout << res.size() << "
    ";
    128             for (auto it : res) cout << it << "
    ";
    129         }
    130     }
    131     return 0;
    132 }
    View Code

    J. Jumbled String

    Solved.

    题意:

    要求构造一个01串,使得所有子序列中,$00出现a次,01出现b次,10出现c次,11出现d次$

    思路:

    显然,如果$a > 0, b > 0, 那么其中0的个数和1的个数是固定的$

    而且有$b + c == cnt[0] cdot cnt[1]$

    $此处cnt 表示 0的个数或者1的个数$

    $那么刚开始0全放全面,1全放后面,然后把1往前面挪动,直到满足条件$

    记得特判几种特殊情况以及$Impossible$

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define ll long long
     5 ll a, b, c, d;
     6 ll n, m, need, remind; 
     7 
     8 ll f(ll x)
     9 {
    10     for (ll i = 1; ; ++i)
    11     {
    12         if ((i * (i - 1) / 2) > x) return -1;
    13         if (i * (i - 1) / 2 == x) return i;
    14     }
    15 }
    16 
    17 int main()
    18 {
    19     while (scanf("%lld%lld%lld%lld", &a, &b, &c, &d) != EOF)
    20     {
    21         if (!a && !b && !c && !d) puts("0");
    22         else if (!b && !c && !d)
    23         {
    24             n = f(a);
    25             if (n == -1) puts("impossible");
    26             else 
    27             {
    28                 for (int i = 1; i <= n; ++i) putchar('0');
    29                 puts("");
    30             }
    31         }    
    32         else if (!a && !b && !c)
    33         {
    34             m = f(d);
    35             if (m == -1) puts("impossible");
    36             else
    37             {
    38                 for (int i = 1; i <= m; ++i) putchar('1');
    39                 puts("");
    40             }
    41         }
    42         else
    43         {
    44             n = f(a), m = f(d);
    45             if (n == -1 || m == -1 || n * m != (b + c)) puts("impossible"); 
    46             else
    47             {
    48                 need = b / n;
    49                 remind = b % n;
    50                 for (int i = 1; i <= m - need - (remind ? 1 : 0); ++i) putchar('1');
    51                 for (int i = 1; i <= n; ++i)
    52                 {
    53                     putchar('0');
    54                     if (i == remind) putchar('1');
    55                 }
    56                 for (int i = 1; i <= need; ++i) putchar('1'); 
    57                 puts("");
    58             }
    59         }
    60     }
    61     return 0;
    62 }
    View Code

    K. King's Colors

    Solved.

    题意:

    给出一棵树,相邻结点不能染相同颜色,求恰好染k种颜色的方案数。

    思路:

    因为是一棵树,那么如果所求的是$<=k种颜色的方案数 答案就是k * (k - 1)^ {n -1}$

    $因为根节点有k种选择,其他结点都有k - 1种选择$

    但实际上这包含了$k - 2, k - 3, k - 4 cdots 2的方案数 容斥一下即可$

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 typedef long long ll;
     6 
     7 const int maxn = 2510;
     8 const ll MOD = 1e9 + 7;
     9 
    10 ll fac[maxn], invfac[maxn], inv[maxn];
    11 
    12 ll qpow(ll x,ll n)
    13 {
    14     ll res = 1;
    15     while(n)
    16     {
    17         if(n & 1) res = res * x % MOD;
    18         x = x * x % MOD;
    19         n >>= 1;
    20     }
    21     return res;
    22 }
    23 
    24 void Init()
    25 {
    26     fac[0] = invfac[0] = inv[0] = 1;
    27     fac[1] = invfac[1] = inv[1] = 1;
    28     for(int i = 2; i < maxn; ++i)
    29     {
    30         fac[i] = fac[i - 1] * i % MOD;
    31         inv[i] = inv[MOD % i] * (MOD - MOD / i) % MOD;
    32         invfac[i] = invfac[i - 1] * inv[i] % MOD;    
    33     }
    34 }
    35 
    36 ll calc(int n, int m)
    37 {
    38     if (n < 0 || m < 0) return 0;
    39     if (n == m || m == 0) return 1;
    40     return fac[n] * invfac[m] % MOD * invfac[n - m] % MOD;
    41 }
    42 
    43 int n, k;
    44 
    45 int main()
    46 {
    47     Init();
    48     while(~scanf("%d %d",&n, &k))
    49     {
    50         for(int i = 1, num; i < n; ++i) scanf("%d", &num);
    51         int flag = 1;
    52         ll ans = 0;
    53         for(int i = k; i >= 2; --i, flag = !flag)
    54         {
    55             if(flag) ans = (ans + calc(k, i) * i % MOD * qpow(i - 1, n - 1) % MOD) % MOD;
    56             else ans = (ans - calc(k, i) * i % MOD * qpow(i - 1, n - 1) % MOD + MOD) % MOD;
    57         }
    58         printf("%lld
    ", ans);
    59     }
    60     return 0;
    61 }
    View Code
  • 相关阅读:
    linux tcp调优
    nginx 代理http配置实例
    nginx代理socket tcp/udp
    C++对象数组初始化
    《大型网站技术架构》读书笔记
    内核空间、用户空间和虚拟地址(转)
    集群——LVS理论(转)
    Linux服务器集群系统(一)(转)
    从一个开发的角度看负载均衡和LVS(转)
    ubuntu下允许root用户ssh远程登录
  • 原文地址:https://www.cnblogs.com/Dup4/p/10088650.html
Copyright © 2011-2022 走看看