• 常州大学新生寒假训练会试 题解


    题目链接

    A - 添加逗号

    注意是从后往前三个三个加逗号,最前面不允许有逗号

    #include <bits/stdc++.h>
    using namespace std;
     
    const int maxn = 1e5 + 10;
    char s[maxn];
    char ans[maxn];
    int sz;
     
    int main() {
      scanf("%s", s);
      int len = strlen(s);
      sz = 0;
      int t = 0;
      for(int i = len - 1; i >= 0; i --) {
        ans[sz ++] = s[i];
        ans[sz] = 0;
        t ++;
        if(t % 3 == 0 && i != 0) ans[sz ++] = ',', ans[sz] = 0;
      }
      len = strlen(ans);
      for(int i = len - 1; i >= 0; i --) {
        printf("%c", ans[i]);
      }
      printf("
    ");
      return 0;
    }
    

      

    B - 对称

    可以递归求解。

    #include <bits/stdc++.h>
    using namespace std;
     
    long long n, m;
     
    long long work(long long r, long long c) {
      if(r % 2 == 0 || c % 2 == 0) return 0LL;
      return 4 * work(r / 2, c / 2) + 1LL;
    }
     
    int main() {
      scanf("%lld%lld", &n, &m);
      printf("%lld
    ", work(n, m));
      return 0;
    }
    

      

    C - 竞赛技巧

    排序。

    #include <bits/stdc++.h>
    using namespace std;
     
    const int maxn = 1e5 + 10;
    struct X{
      int h, m, s;
      void out() {
        printf("%d %d %d
    ", h, m, s);
      }
    }s[maxn];
    int n;
     
    bool cmp(const X&a, const X&b) {
      if(a.h != b.h) return a.h < b.h;
      if(a.m != b.m) return a.m < b.m;
      return a.s < b.s;
    }
     
    int main() {
      scanf("%d", &n);
      for(int i = 1; i <= n; i ++) {
        scanf("%d%d%d", &s[i].h, &s[i].m, &s[i].s);
      }
      sort(s + 1, s + 1 + n, cmp);
      for(int i = 1; i <= n; i ++) {
        s[i].out();
      }
      return 0;
    }
    

      

    D - 训练技巧

    设$dp[0][i]$表示以$i$为结尾的最大价值,$dp[1][i]$表示$j(j < i)$为结尾的最大价值。可见,该$dp$为$O(n^2)$效率的。

    显然,$dp[0][i] = mathop {max }limits_{j = i - k}^{i - 1} (dp[1][j] + i - j) = i + mathop {max }limits_{j = i - k}^{i - 1} (dp[1][j] - j)$。

    只要维护$dp[1][j] - j$的最大值即可,用单调队列 or 线段树就可以了。

    #include <bits/stdc++.h>
    using namespace std;
     
    const int maxn = 1e5 + 10;
    int n, k;
    long long a[maxn];
    long long dp[2][maxn];
    long long sum[maxn];
     
    int q[5 * maxn];
    int first, last;
     
    bool check2(int a, int b) {
      if(dp[1][b] - dp[1][a] > sum[b] - sum[a]) return 1;
      return 0;
    }
     
    int main() {
      scanf("%d%d", &n, &k);
      for(int i = 1; i <= n; i ++) {
        scanf("%lld", &a[i]);
        sum[i] = sum[i - 1] + a[i];
      }
       
      /*
       dp[0][i] // 以i结尾
       dp[1][i] // 不以i结尾
       */
       
      first = 0, last = -1;
      
      for(int i = 1; i <= k; i ++) {
        dp[0][i] = sum[i];
        dp[1][i + 1] = max(dp[0][i], dp[1][i]);
        while(1) {
          if(last - first + 1 == 0) break;
          if(check2(q[last], i)) last --;
          else break;
        }
        last ++;
        q[last] = i;
      }
       
      for(int i = k + 1; i <= n; i ++) {
        while(1) {
          if(last < first) break;
          if(i - q[first] > k) first ++;
          else break;
        }
      /*
        printf("debug %d: ", i);
        for(int i = first; i <= last; i ++) {
          printf("%d ", q[i]);
        }
        printf("
    ");
        */
     
        dp[0][i] = dp[1][q[first]] + sum[i] - sum[q[first]];
        dp[1][i + 1] = max(dp[0][i], dp[1][i]);
         
        while(1) {
          if(last - first + 1 == 0) break;
          if(check2(q[last], i)) last --;
          else break;
        }
         
        last ++;
        q[last] = i;
        /*
        printf("debug %d: ", i);
        for(int i = first; i <= last; i ++) {
          printf("%d ", q[i]);
        }
        printf("
    ");
         */
      }
       
      for(int i = 1; i <= n; i ++) {
       // printf("%d %lld %lld
    ", i, dp[0][i], dp[1][i]);
      }
       
      long long ans = 0;
      for(int i = 1; i <= n; i ++) {
        ans = max(ans, dp[0][i]);
        ans = max(ans, dp[1][i]);
      }
      printf("%lld
    ", ans);
      return 0;
    }
    

      

    E - 这是一个数学题

    化简之后可以发现$A_i = A_0*frac{n-i}{n} + A_n*frac{i}{n}$,这样就很容易求解了。

    import java.math.BigDecimal;
    import java.math.BigInteger;
    import java.util.*;
     
    public class Main {
        static Scanner cin = new Scanner(System.in);
         
        public static void main(String[] args) {
            int n = cin.nextInt();
            long a0 = cin.nextLong();
            long an = cin.nextLong();
            int Q = cin.nextInt();
            while(Q -- > 0) {
                long L = cin.nextLong();
                long R = cin.nextLong();
                long len = R - L + 1;
                 
                BigInteger ans = BigInteger.ZERO;
                BigInteger A = BigInteger.ZERO;;
                BigInteger B = BigInteger.ZERO;;
                 
                long x = len * n;
                long y = (L + R) * len / 2;
                 
                A = BigInteger.valueOf(x).subtract(BigInteger.valueOf(y));
                A = A.multiply(BigInteger.valueOf(a0));
                A = A.divide(BigInteger.valueOf(n));
                 
                B = BigInteger.valueOf(an).multiply(BigInteger.valueOf(y)).divide(BigInteger.valueOf(n));
                 
                ans = A.add(B);
                 
                System.out.println(ans);
            }
        }
    }
    

      

    F - 大佬的生日大礼包

    如果$x$个人能满足,那么$[0,x]$个人都能满足,依据这个性质,我们可以对答案进行二分。

    接下来就是验证$x$个人能否满足:

    首先观察到,无论是哪一种大礼包,都会用掉一个U盘和一个鼠标,除此之外,每种礼包再外加一个物品。

    因此U盘或者鼠标数量不足$x$个,则无解。

    将U盘和鼠标数量都减去$x$个后,问题就变成了:三种物品分别有$p_0$,$p_1$,$p_2$个,问是否存在排列方案使得相邻两个物品种类不同。

    只要验证$sum_{i=0}^2min(p_i, frac{x+1}{2})$和$x$的大小关系即可。

    #include <bits/stdc++.h>
    using namespace std;
     
    int T, a, b ,c;
     
    int check(int x) {
      int p[3];
       p[0] = a - x;
       p[1] = b - x;
       p[2] = c;
      if(p[0] < 0 || p[1] < 0) return 0;
      for(int i = 0; i < 3; i ++) {
        p[i] = min(p[i], (x + 1) / 2);
      }
      if(p[0] + p[1] + p[2] >= x) return 1;
      return 0;
    }
     
    int main() {
      scanf("%d", &T);
      while(T --) {
        scanf("%d%d%d", &a, &b, &c);
        int L = 0, R = a + b + c, ans = 0;
        while(L <= R) {
          int mid = (L + R) / 2;
          if(check(mid)) ans = mid, L = mid + 1;
          else R = mid - 1;
        }
        printf("%d
    ", ans);
      }
      return 0;
    }
    

      

    G - 零下e度

    公式1:$frac{1}{e}= sum_{i = 0}^{infty} (-1)^ifrac{1}{i!}$

    公式2:$e= sum_{i = 0}^{infty} frac{1}{i!}$

    知道上面这个公式就会做了。这题卡常数,$mod$如果不是const定义的话容易超时。

    #include <bits/stdc++.h>
    using namespace std;
     
    const int mod = 998244353LL;
    long long ans;
    int n;
     
    int main() {
      scanf("%d", &n);
      long long u = 1;
      int p = (n % 2) ? -1 : 1;
      for(int i = n; i >= 1; i --) {
        ans = (ans + p * u + mod) % mod;
        u = (u * i) % mod;
        p = p * -1;
      }
      ans = (ans + u) % mod;
      printf("%lld
    ", ans);
      return 0;
    }
    

      

    H - 酸碱滴定

    模拟题。

    #include <bits/stdc++.h>
    using namespace std;
    
    double eps = 1e-8;
    
    double work(double x) {
      int a = x * 10000;
      int b = a / 10 % 10;
      if(b < 5) return (int)(a / 100) / 100.0;
      else if(b > 5) return ((int)(a / 100) + 1) / 100.0;
      else {
        if (x * 10000 - a > eps) return ((int)(a / 100) + 1) / 100.0;
        else {
          if (a / 100 % 10 % 2) return ((int)(a / 100) + 1) / 100.0;
          else return (int)(a / 100) / 100.0;
        }
      }
    }
    
    int main() {
      int T;
      scanf("%d", &T);
      while(T --) {
        double a, b, c;
        scanf("%lf%lf%lf", &a, &b, &c);
        printf("%.2lf
    ", work(a * c / b));
      }
      return 0;
    }
    

    I - 合成反应

    暴力,每次判断那些还不能执行的方程式,直到不能增加元素为止。

    #include <bits/stdc++.h>
    using namespace std;
     
    const int maxn = 1e5 + 10;
    int f[maxn];
    int a[maxn], b[maxn], c[maxn];
    int q, n, k, m;
    set<int> st;
     
    int main() {
      scanf("%d%d%d%d", &k, &n, &m, &q);
      for(int i = 1; i <= n; i ++) {
        scanf("%d%d%d", &a[i], &b[i], &c[i]);
        st.insert(i);
      }
      for(int i = 1; i <= m; i ++) {
        int x;
        scanf("%d", &x);
        f[x] = 1;
      }
      vector<int> vec;
      while(!st.empty()) {
        set<int>::iterator it;
        vec.clear();
        for(it = st.begin(); it != st.end(); it ++) {
          int id = *it;
          if((f[a[id]] && f[b[id]]) || f[c[id]]) {
            f[a[id]] = 1;
            f[b[id]] = 1;
            f[c[id]] = 1;
            vec.push_back(id);
          }
        }
        if(vec.size() == 0) break;
         
        for(int i = 0; i < vec.size(); i ++) {
          st.erase(vec[i]);
        }
      }
       
      while(q --) {
        int x;
        scanf("%d", &x);
        printf("%s
    ", f[x] ? "Yes" : "No");
      }
      return 0;
    }
    

      

    J - 同分异构体

    手算 or OEIS

    #include <bits/stdc++.h>
    using namespace std;
     
    int ans[] = {1, 1, 1, 1, 2, 3, 5, 9, 18, 35, 75, 159};
     
    int main() {
      int n;
      scanf("%d", &n);
      printf("%d
    ", ans[n]);
      return 0;
    }
    

      

  • 相关阅读:
    SDOI2020游记
    Git和GitHub详解
    P1251 餐巾计划问题
    P2824 [HEOI2016/TJOI2016]排序
    P3224 [HNOI2012]永无乡
    P3605 [USACO17JAN]Promotion Counting晋升者计数
    P4314 CPU监控
    P2939 [USACO09FEB]改造路Revamping Trails
    P4254 [JSOI2008]Blue Mary开公司
    P1772 [ZJOI2006]物流运输
  • 原文地址:https://www.cnblogs.com/zufezzt/p/8428551.html
Copyright © 2020-2023  润新知