• CDUT2020寒假训练第一场 题解


    好久没有更博客了

    前两天跑去打美赛,第一次参加数学建模,选了E题,没想到一直理解不了第一个问题的意思,找了快两天数据……想着用多元非线性回归,结果数据是线性的,线性回归r值为1……

    心态不太好于是放弃二月份准备三月份的了orz

    我讨厌塑料垃圾

    以下正文

    A

    CF 1030C

    链接:http://codeforces.com/problemset/problem/1030/C

     

    题意:给100个以内的数字,求是否能把这些数字划分成两个或以上和相等的部分,不能改变数字顺序

    思路:因为最多只有100个数,可以直接暴力求解,2个思路,一个是求和之后直接遍历0到和之间的数,一个是遍历和的因数。

    坑点:注意0的情况(全0,末尾0),n个数相同的情况

    代码如下(写的比较复杂orz):

     1 #include <iostream>
     2 #include <cstdio>
     3 
     4 const int N = 105;
     5 int a[N];
     6 
     7 int main(){
     8     int n, sum = 0;
     9     char s[2];
    10     scanf("%d", &n);
    11     gets(s);
    12     for(int i = 0; i < n; i ++ ){
    13         scanf("%c",&a[i]);
    14         a[i] -= '0';
    15         sum += a[i];
    16     }
    17     bool f = true;
    18     for(int i = 0; i < n; i ++ ){
    19         if(a[i] != 0){
    20             f = false;
    21             break;
    22         }
    23     }
    24     if(f){
    25         printf("YES
    ");
    26         return 0;
    27     }
    28     bool f2 = true;
    29     for(int i = 0; i < n - 1; i ++ ){
    30         if(a[i] != a[i+1]){
    31             f2 = false;
    32             break;
    33         }
    34     }
    35     if(f2){
    36         printf("YES
    ");
    37         return 0;
    38     }
    39     bool flag = false;
    40     for(int x = 2; sum / x >= 1 && x != n; x ++ ){
    41         if(sum % x == 0){
    42             int cnt = 0;
    43             for(int i = 0, j = 0; j <= n;){
    44                 if(cnt < sum / x){
    45                     cnt += a[j++];
    46                 }
    47                 else if(cnt == sum / x){
    48                     if(j != n && a[j] != 0)
    49                         i = j, cnt = 0;
    50                     else if(j != n && a[j] == 0)
    51                         j ++ ;
    52                     else{
    53                         flag = true;
    54                         break;
    55                     }
    56                 }
    57                 else if(cnt > sum / x){
    58                     break;
    59                 }
    60             }
    61             if(flag) break;
    62         }
    63         if(flag) break;
    64     }
    65     if(flag) printf("YES
    ");
    66     else printf("NO
    ");
    67     return 0;
    68 }
    View Code

    B

    CF 1038D

    链接:http://codeforces.com/problemset/problem/1038/D

     题意:给一串数字,每个数可以减去它左右两边的数,求减到最后剩下的数的最大值

     思路:分为两种情况,一种是有正有负的,那么答案直接是绝对值相加,一种是全为正或全为负(含0),那么答案直接是绝对值相加的总和,减去离0最近的那个数的绝对值的两倍。

    代码如下:(因为clion的原因不知道为什么用不了min

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cmath>
     4 #include <algorithm>
     5 const int N = 5e5 + 10;
     6 typedef long long LL;
     7 int a[N];
     8 
     9 int min(int y, int x);
    10 
    11 int main(){
    12     int n;
    13     scanf("%d", &n);
    14     int x = 0x3f3f3f3f;
    15     LL sum = 0;
    16     bool pos = false, neg = false;
    17     if(n == 1){
    18         scanf("%d", &a[0]);
    19         printf("%d", a[0]);
    20         return 0;
    21     }
    22     else
    23         for(int i = 0; i < n; i ++ ){
    24             scanf("%d", &a[i]);
    25             if(a[i] >= 0) {
    26                 pos = true;
    27                 x = min(a[i], x);
    28                 sum += a[i];
    29             }
    30             else if(a[i] <= 0){
    31                 neg = true;
    32                 x = min(abs(a[i]), x);
    33                 sum += abs(a[i]);
    34             }
    35         }
    36     if(neg && pos)
    37         printf("%lld", sum);
    38     else
    39         printf("%lld", sum - 2 * x);
    40     return 0;
    41 }
    42 
    43 int min(int y, int x) {
    44     if(x > y) return y;
    45     else return x;
    46 }
    View Code

    C

    CF 234C

    链接:http://codeforces.com/problemset/problem/234/C

     

     题意:给出一行温度,通过一系列变换要使得某个数之前(包括这个数)都小于零,之后的数都大于零,求最小变换次数。

    思路:通过计数存下当前数及当前数以前有多少个小于零和大于零的数,变换次数就等于该数后面小于零的数的个数加上该数前面大于零的数的个数。

    注意此题需要用到文件读入输出。

    代码如下:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 using namespace std;
     7 const int N = 1e5 + 10;
     8 int a[N], sump[N], sumn[N];
     9 
    10 int main(){
    11     freopen("input.txt", "r", stdin);
    12     freopen("output.txt", "w", stdout);
    13     int n;
    14     scanf("%d", &n);
    15     //sump[0] = 0;
    16     //sumn[0] = 0;
    17     for(int i = 1; i <= n ; i ++ ){
    18         scanf("%d", &a[i]);
    19         if(a[i] > 0){
    20             sump[i] = sump[i-1] + 1;
    21             sumn[i] = sumn[i-1];
    22         }
    23         else if(a[i] < 0){
    24             sumn[i] = sumn[i-1] + 1;
    25             sump[i] = sump[i-1];
    26         }
    27         else{
    28             sump[i] = sump[i-1] + 1;
    29             sumn[i] = sumn[i-1] + 1;
    30         }
    31     }
    32     int minn = 0x3f3f3f3f;
    33     for(int i = 1; i < n ; i ++){
    34         int x = sump[i] + sumn[n] - sumn[i];
    35         minn = min(minn, x);
    36     }
    37     printf("%d", minn);
    38     return 0;
    39 }
    View Code

    G

    CF 1206B

     

     题意:给一行数,通过进行加一减一的操作使这行数的乘积为1

    思路:计算该数与-1和1的距离,离谁近就变为谁,累加上加减一的次数,记录转化为-1的个数以及0的个数。最后若-1为奇数,则考虑通过将0转变成-1或将一个-1再加2次成为1。

    注意答案需要开long long

    代码如下:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 using namespace std;
     7 const int N = 1e5 + 10;
     8 int a[N];
     9 
    10 int main(){
    11     int n;
    12     scanf("%d", &n);
    13     int flag = 0;//记录-1的个数
    14     int f = 0;//记录0的个数
    15     long long ans = 0;
    16     for(int i = 0; i < n ; i ++){
    17         scanf("%d", &a[i]);
    18         int x = abs(a[i] - 1);
    19         int y = abs(a[i] + 1);
    20         if(a[i] == 0)
    21             f++;
    22         else if(x < y){
    23             ans += x;
    24         }
    25         else {
    26             ans += y;
    27             flag ++;
    28         }
    29     }
    30     if(flag % 2 == 1){
    31         if(f)
    32             ans += f;
    33         else
    34             ans = ans + 2;
    35     }
    36     else
    37         ans += f;
    38     printf("%lld", ans);
    39     return 0;
    40 }
    View Code

    H

    CF 1245B

     

     题意:给出对手的石头剪刀布顺序,给出己方每种手势的总数,问是否能赢过对手(赢的次数大于向上取整的n/2),如果可以写出出手势的顺序。

    思路:先判断能不能赢,然后先把可以赢的填进对应的场次,再把剩下的abc分配去输的场合。

    代码如下:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <string.h>
     5 #include <cmath>
     6 using namespace std;
     7 const int N = 110;
     8 char aa[N], bb[N];
     9 
    10 int main(){
    11     int t;
    12     scanf("%d", &t);
    13     while(t --){
    14         int n;
    15         scanf("%d", &n);
    16         char str[2];
    17         int a, b, c, r = 0, p = 0, s = 0;
    18         scanf("%d %d %d", &a, &b, &c);
    19         scanf("%c", &str[0]);
    20         for(int i = 0; i < n; i ++ ){
    21             scanf("%c", &aa[i]);
    22             if(aa[i] == 'R') r++;
    23             else if(aa[i] == 'P') p++;
    24             else s++;
    25         }
    26         scanf("%c", &str[0]);
    27         int ans1 = 0, ans2 = 0, ans3 = 0;
    28         ans1 += min(a, s);
    29         ans2 += min(b, r);
    30         ans3 += min(c, p);
    31         int ans = ans1 + ans2 + ans3;
    32         int x = ceil(double(n) / 2.0);
    33         memset(bb, 0, sizeof bb);
    34         if(ans >= x){
    35             printf("YES
    ");
    36             for(int i = 0; i < n ; i ++ ){
    37                 if(aa[i] == 'S' && ans1)
    38                     bb[i] = 'R', ans1 --, a--;
    39                 else if(aa[i] == 'R' && ans2)
    40                     bb[i] = 'P', ans2 --, b--;
    41                 else if(aa[i] == 'P' && ans3)
    42                     bb[i] = 'S', ans3 --, c--;
    43             }
    44             for(int i = 0; i < n ; i ++ ){
    45                 if(bb[i] != 0)
    46                     printf("%c", bb[i]);
    47                 else{
    48                     if(a) putchar('R'), a --;
    49                     else if(b) putchar('P'), b --;
    50                     else if(c) putchar('S'), c --;
    51                 }
    52             }
    53             cout<<endl;
    54         }
    55         else
    56             cout<<"NO"<<endl;
    57     }
    58     return 0;
    59 }
    View Code
  • 相关阅读:
    Navicat Premium 12连接Oracle时提示oracle library is not loaded的问题解决
    事务传播机制Propagation.REQUIRES_NEW
    @ApiImplicitParams、ApiImplicitParam的使用
    启动微服务项目的时候报redisInit错误---本地启动redis服务
    Swagger介绍及使用
    mybaitis框架-trim标签
    pgadmin怎样创建新的连接
    微服务项目启动
    管理中第一可怕之事(2) . 分类: 项目管理 2014-06-25 18:54 257人阅读 评论(0) 收藏
    管理中第一可怕之事(1) . 分类: 项目管理 2014-06-25 18:53 264人阅读 评论(0) 收藏
  • 原文地址:https://www.cnblogs.com/moomight/p/12409825.html
Copyright © 2020-2023  润新知