zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 47 (Rated for Div. 2) 题解

    题目链接:http://codeforces.com/contest/1009

    A. Game Shopping 题目:

    题意:有n件物品,你又m个钱包,每件物品的价格为ai,每个钱包里的前为bi。你站在第一件物品前,如果你的第一个钱包能购买这件物品,你第一个钱包的钱直接消失(就相当于你是用第一个钱包里的所有钱购买了这件物品,不会找钱),如果无法购买那么就跳到下一件物品,以此类推,问你总共能购买多少件物品。

    思路:直接模拟即可。

    代码如下:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int maxn = 1007;
     5 int n, m, ans;
     6 int a[maxn], b[maxn];
     7 
     8 int main() {
     9     cin >>n >>m;
    10     for(int i = 0; i < n; i++) {
    11         cin >>a[i];
    12     }
    13     for(int i = 0; i < m; i++) {
    14         cin >>b[i];
    15     }
    16     for(int i = 0, j = 0; i < n ; i++) {
    17         if(j >= m) break;
    18         if(b[j] >= a[i]) {
    19             j++;
    20             ans++;
    21         }
    22     }
    23     cout <<ans <<endl;
    24     return 0;
    25 }
    View Code

    B. Minimum Ternary String  题目:

    题意:给你一个只含012的串,0可以和1交换,1可以和2交换,0不可以和2交换,问进行多次交换后字典序最小的串是啥。

    思路:因为1可以和02交换,所以要想字典序最小1必须全在2前面;2不能和0换,所以2和0的相对位置不变。故此题的思路就是将第一个2前的的所有0放在最前面,然后紧跟所有的1,后面的2和0就按照原顺序即可。方法1:暴力。方法2:借用vetctor。

    代码如下:

     1 //方法一
     2 //#include <bits/stdc++.h>
     3 //using namespace std;
     4 //
     5 //const int maxn = 1e5 + 7;
     6 //int a[maxn];
     7 //string s, t;
     8 //
     9 //int main() {
    10 //    cin >>s;
    11 //    int cnt1 = 0, cnt2 = 0, cnt3 = 0;
    12 //    int pos = -1;
    13 //    for(int i = 0; i <s.size(); i++) {
    14 //        if(s[i] != '0') {
    15 //            pos = i;
    16 //            break;
    17 //        }
    18 //    }
    19 //    for(int i = s.size() - 1; i >= pos; i--) {
    20 //        if(s[i] == '0') {
    21 //            cnt1++;
    22 //            if(cnt3 > 0) {
    23 //                for(int j = 0; j < cnt3; j++) {
    24 //                    t += '2';
    25 //                }
    26 //                cnt3 = 0;
    27 //            }
    28 //        } else if(s[i] == '1') {
    29 //            cnt2++;
    30 //        } else if(s[i] == '2') {
    31 //            cnt3++;
    32 //            if(cnt1 > 0) {
    33 //                for(int j = 0; j <cnt1; j++) {
    34 //                    t += '0';
    35 //                }
    36 //                cnt1 = 0;
    37 //            }
    38 //        }
    39 //    }
    40 //    for(int i = 0; i < cnt3; i++) {
    41 //        t += '2';
    42 //    }
    43 //    for(int i = 0; i <cnt2; i++) {
    44 //        t += '1';
    45 //    }
    46 //    for(int i = 0; i < pos; i++) {
    47 //        t += '0';
    48 //    }
    49 //    for(int i = 0; i < cnt1; i++) {
    50 //        t += '0';
    51 //    }
    52 //    reverse(t.begin(), t.end());
    53 //    cout <<t <<endl;
    54 //    return 0;
    55 //}
    56 
    57 //方法二
    58 #include <bits/stdc++.h>
    59 using namespace std;
    60 
    61 string s;
    62 vector<char> v;
    63 
    64 int main() {
    65     cin >>s;
    66     int cnt = 0;
    67     for(int i = 0; i < s.size(); i++) {
    68         if(s[i] == '1') cnt++;
    69         else v.push_back(s[i]);
    70     }
    71     int flag = 0;
    72     for(int i = 0; i < v.size(); i++) {
    73         if(v[i] == '2' && !flag) {
    74             while(cnt--) {
    75                 cout<<"1";
    76             }
    77             cout <<"2";
    78             flag = 1;
    79         } else {
    80             cout <<v[i];
    81         }
    82     }
    83     //可能没有0、1,所以要在这里输出一遍
    84     for(int i = 0; i <cnt; i++) {
    85         cout <<"1";
    86     }
    87     cout <<endl;
    88     return 0;
    89 }
    View Code

    C. Annoying Present 题目:

    题意:有n个元素,初始为0,进行m次操作,每次操作给你x和d,你选择一个i,然后对每个元素(记为j,包括i)进行操作ai+x+d*dist(i,j),问最后所有元素的最大平均值是多少。

    思路:这个就是个贪心+公式题。这题的贪心方法是当d>0时,i选择最左(最右都可以,因为dist(i,j)是一样的,最后是算平均值,所有加在哪个元素上是没有区别的;当d<0时,选择最中间,此处要将n分奇偶,因为奇数和偶数是有所区别的。当推出这些之后会发现这题就是个等差数列求和,注意会爆int,比赛的时候就是被这个点坑死。ps.赛后这题是被hack人数最多的,本场hack数排第一的大佬就是这题hack了600多人,第一个坑点就是求和不能用double,会有精度损失,第二个坑点就是不要先除,要先求和再除。

    代码实现如下:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 typedef long long ll;
     5 ll n, m, x, d, ans;
     6 
     7 int main() {
     8     scanf("%I64d%I64d", &n, &m);
     9     while(m--) {
    10         scanf("%I64d%I64d", &x, &d);
    11         ans += x * n;
    12         if(d > 0) {
    13             ans += (n - 1) * n / 2 * d;
    14         }  else {
    15             if(n & 1) ans += (n / 2 + 1) * (n / 2) * d;
    16             else ans += (n / 2) * (n / 2) * d;
    17         }
    18     }
    19     printf("%.8f
    ", ans * 1.0 / n);
    20     return 0;
    21 }
    View Code

    D. Relatively Prime Graph 题目:

    题意:构造一个只有n个点m条边的联通图,且相邻节点的编号要互质。

    思路:当m<n-1时,由图联通知至少需要n-1条边,因此此处为impossible。1与所有的数都互质,所以此处保证了联通性。因为只需要m条边,由欧拉函数可以证得此题暴力的复杂度是稍大于O(m),我只会估算,具体证明暂时不会……因此此题可以暴力水过。

    代码如下:

     1 #include <cmath>
     2 #include <cstdio>
     3 #include <iostream>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 const int maxn = 1e5 + 7;
     8 int n, m, t;
     9 
    10 struct node {
    11     int x, y;
    12 }edge[maxn];
    13 
    14 int main() {
    15     cin >>n >>m;
    16     if(n - 1 > m) {
    17         puts("Impossible");
    18         return 0;
    19     }
    20     int flag = 0;
    21     for(int i = 1; i <= n; i++) {
    22         for(int j = i + 1; j <= n; j++) {
    23             if( __gcd(i, j) == 1) {
    24                 edge[t].x = i;
    25                 edge[t].y = j;
    26                 t++;
    27                 if(t >= m) {
    28                     flag = 1;
    29                     break;
    30                 }
    31             }
    32         }
    33         if(flag) break;
    34     }
    35     if(flag) {
    36         puts("Possible");
    37         for(int i = 0; i < m; i++) {
    38             cout <<edge[i].x <<" " <<edge[i].y <<endl;
    39         }
    40     } else {
    41         puts("Impossible");
    42     }
    43     return 0;
    44 }
    View Code

    赛后补题

    E. Intercity Travelling 题目:

    题意:Leha从数轴的0到n,中间的整数点都有可能有休息点也可能没有休息点。当你连续坐k站时,每两站间的疲劳值为a1,a2……ak,如果第k站有休息点,那么你可以在此处休息,然后接下来的站点的疲劳值又从a1开始,否则继续为ak+1。题目给你n和ai,每个站点有休息点的概率都是1/2,问你期望值*2^(n-1)的值。

    思路:我们知道从0到1的疲劳值一定为a1,1到2的疲劳值为a1(1/2),a2(1/2),括号里面为概率,当1有休息点时为a1,否则为a2;2到3的疲劳值为a1(1/2),a2(1/4),a3(1/4)……以此类推得到下图:

    然后将他们加起来乘以2^(n-1)即可。ps.别用cin,cout,会T9,别问我怎么知道的!

    代码实现如下:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 typedef long long ll;
     5 const int mod = 998244353;
     6 const int maxn = 1e6 + 7;
     7 int n;
     8 ll ans;
     9 ll a[maxn], p[maxn];
    10 
    11 int main() {
    12     scanf("%d", &n);
    13     p[0] = 1;
    14     for(int i = 1; i <= n; i++) {
    15         p[i] = p[i-1] * 2 % mod;
    16     }
    17     for(int i = 1; i <= n; i++) {
    18         scanf("%I64d", &a[i]);
    19     }
    20     ans = a[n];
    21     for(int i = 1; i < n; i++) {
    22         ans = (ans + (a[i] * (p[n - i] + p[n - i - 1] * (n - i) % mod) % mod) % mod) % mod;
    23     }
    24     printf("%I64d
    ", ans);
    25     return 0;
    26 }
    View Code
  • 相关阅读:
    关闭游标
    OCP-1Z0-053-200题-19题-601
    OCP-1Z0-053-200题-17题-99
    OCP-1Z0-053-200题-18题-100
    OCP-1Z0-053-V13.02-99题
    OCP-1Z0-053-200题-16题-98
    OCP-1Z0-053-200题-15题-15
    OCP-1Z0-053-200题-14题-675
    OCP-1Z0-053-200题-13题-97
    OCP-1Z0-053-200题-12题-96
  • 原文地址:https://www.cnblogs.com/Dillonh/p/9313493.html
Copyright © 2011-2022 走看看