• ZAFU 新生赛题解


    一篇迟到的题解,本以为大家兴趣不大,但是有同学问了,本人觉得还是应该写一下。

    T酱和他的数学题

    要求判断末尾有多少个0

    我们分析一下就可以知道0只能是来自2 和 5 的乘积。

    对于每一个数字我们只需要去判断可以分解出多少个2和5就可以,其中5的出现次数一定会小于2的出现次数。

    由于是阶乘的阶乘

    所以我们只需要暴力一遍,维护5出现次数的前缀和的前缀和就可以了

     1 #include <stdio.h>
     2 int cal(int x)
     3 {
     4     int res = 0;
     5     while(x)
     6     {
     7         if(x%5) break;
     8         x /= 5;
     9         res++;
    10     }
    11     return res;
    12 }
    13 int main()
    14 {
    15     long long res, tmp;
    16     int n;
    17     while(scanf("%d", &n) != EOF)
    18     {
    19         res = tmp = 0;
    20         for(int i = 1; i <= n; i++)
    21         {
    22             tmp += cal(i);
    23             res += tmp;
    24         }
    25         printf("%lld
    ", res);
    26     }
    27 }

    Vic和骑士

    自己手推一下 n = 4 和n = 5的情况, 就会发现规律,只要RB交错排列就可以

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 
     7 int main()
     8 {
     9     int T, n, ca = 0;
    10     while(scanf("%d", &n) != EOF)
    11     {
    12         for(int i = 1; i <= n; i++)
    13         {
    14             if(i%2) 
    15                 for(int j = 1; j <= n; j++)
    16                     if(j%2) putchar('B');
    17                     else putchar('R');
    18             if(i%2==0) 
    19                 for(int j = 1; j <= n; j++)
    20                     if(j%2) putchar('R');
    21                     else putchar('B');
    22                     
    23             putchar('
    ');
    24         }
    25         putchar('
    ');
    26     }
    27     
    28 }

    Vic与水题

    根据题目输出就可以, 但是我们提交的输出样例显示有点问题,在题面里也说明了

     1 #include <iostream>
     2 using namespace std;
     3 int main()
     4 {
     5     int T, n, flag;
     6     cout<<"#include<stdio.h>"<<endl;
     7     cout<<"int main()"<<endl;
     8     cout<<"{"<<endl;
     9     cout<<"int n;"<<endl;
    10     cout<<"n = 10;"<<endl;
    11     cout<<"printf("%d", n);"<<endl;
    12     cout<<"return 0;"<<endl;
    13     cout<<"}";
    14 }

    保护牛奶

    对于这一题,我们可以发现,牛奶被放成了一圈,并且只能取连续的。

    贪心策略是利用圆的对称性来反制对手,所以只有当数量为1 或 2 或 3 时, 先手才赢的机会

     1 #include <iostream>
     2 #include <cstdio>
     3 using namespace std;
     4 int main()
     5 {
     6     int T, n, flag;
     7     while(scanf("%d", &T) != EOF)
     8     {
     9         while(T--)
    10         {
    11             scanf("%d", &n);
    12             if(n<=3&&n>=1) cout<<"milk will die!!!"<<endl;
    13             else cout<<"milk is alive!!!"<<endl;
    14         }
    15         
    16     }
    17     
    18 }

    当老板

    这个题目是一个二分题,但是相对于传统的二分,我们需要计算上界或者下界来保证二分的顺利进行.

    讲一下二分的思路,主要是check比较难

    对于check的值  我们假设是X,每一个员工的可接受的工资是[Li, Ri]

    那么对于Li>X 的员工只能是让他排在中位数的右边

    对于Ri<X的员工只能是让他排在中位数的左边

    然后剩下的我们进行最优分配,如果左边此时还没达到要求人数的一半,那么应该补足左边,这些人发放最小工资,右边的人则是发放X的工资。最后判读这样的分配下花费是否够用可以。

    具体看代码吧

     1 #include <stdio.h>
     2 #include <cstring>
     3 #include <vector>
     4 #include <set>
     5 #include <algorithm>
     6 using namespace std;
     7 struct node
     8 { 
     9     int l, r;
    10     bool operator < (struct node a)
    11     {
    12         return l < a.l;
    13     }
    14 }a[200009];
    15 typedef long long ll;
    16 int T, n, l, r, mid;
    17 ll sum;
    18 bool check(int x)
    19 {
    20     vector <struct node> ve;
    21     ve.clear();
    22     int num = 0;
    23     ll res = 0;
    24     for(int i = 1; i <= n; i++)
    25         if(a[i].r<x) 
    26         {
    27             res += a[i].l;
    28             num++;
    29         }
    30         else if(a[i].l>x) 
    31         {
    32             res += a[i].l;
    33         }else ve.push_back(a[i]);
    34     
    35     if(num>=n/2+1) return false;
    36     
    37     int size = ve.size();
    38     
    39     for(int i = 0; i < size; i++)
    40     if(num<n/2)
    41     {
    42         res += ve[i].l;
    43         num++;
    44     }else res += x;
    45     
    46     return res <= sum;
    47 }
    48 
    49 int main()
    50 {
    51     scanf("%d", &T);
    52     while(T--)
    53     {
    54         scanf("%d %lld", &n, &sum);
    55         for(int i = 1; i <= n; i++)
    56         scanf("%d %d", &a[i].l, &a[i].r);
    57     
    58         r = 1e9;
    59         
    60         sort(a+1, a+1+n);
    61         l = a[n/2+1].l; 
    62     //    printf("%d %d
    ", l, r);
    63         while(l<=r)
    64         {
    65             mid = (l+r) / 2;
    66             if(check(mid))
    67             {
    68                 if(!check(mid+1)) break;
    69                 l = mid+1;
    70             }else r = mid - 1;
    71         }
    72         
    73         printf("%d
    ", mid);
    74     }
    75 }

    滴答滴答

    这是一个暴力模拟的题目,具体的只需要按题意敲就可以,但是比较难处理的是涉及到了大数,我们用数组模拟一下就可以了,考虑到新生赛的难度,所以还是比较好处理的

     1 #include <stdio.h>
     2 #include <cstring>
     3 #include <string.h>
     4 const int N = 2e5+10;
     5 char s[N];
     6 int res[N];
     7 int main()
     8 {
     9     int T, len, pos, num, flag;
    10     scanf("%d", &T);
    11     while(T--)
    12     {
    13         scanf("%s", s+1);
    14         len = strlen(s+1);
    15         num = pos = 0;
    16         s[len+1] = '*';
    17         for(int i = 1; i <= len;)
    18         {
    19             if(s[i]=='d'&&s[i+1]=='a')
    20             {
    21                 flag = 0;
    22                 i = i + 2;
    23                 for(int j = 1; j <= 3 && i <= len; i++, j++)
    24                 if(s[i]<='9'&&s[i]>='0')
    25                 {
    26                     res[++pos] = s[i] - '0';
    27                     flag = 1;    
    28                 } 
    29                 if(flag) num++;
    30             }else if(s[i]=='d'&&s[i+1]=='i')
    31             {
    32                 flag = 0;
    33                 i = i + 2;
    34                 for(int j = 1; j <= 1 && i <= len; i++, j++)
    35                 if(s[i]<='9'&&s[i]>='0')
    36                 {
    37                     res[++pos] = s[i] - '0';
    38                     flag = 1;    
    39                 } 
    40                 if(flag) num++;
    41             }else i++;
    42         }
    43         res[pos] += num;
    44         for(int i = pos; i >= 1; i--)
    45         {
    46             res[i-1] += res[i] / 10;
    47             res[i] %= 10;
    48         }
    49         flag = 0;
    50         for(int i = 0; i <= pos; i++)
    51         {
    52             if(res[i]) flag = 1;
    53             if(flag) printf("%d", res[i]);
    54         }
    55         if(flag) printf("
    ");
    56         else printf("0
    ");
    57     }
    58 }

    取石子游戏

    这是一个大三学长出的防AK题,只要了解SG函数,那么恭喜你,你离AC只有半步之遥了,由于SG函数的时间复杂度是N^2 , 所以肯定要优化,其实我们观察SG函数可以直接得出一个规律,然后这题就AC了。

     1 #include <stdio.h>
     2 int cal(int x)
     3 {
     4     for(int i = 0; ; i++)
     5         if((1<<i) > x) return i % 3;
     6         
     7 }
     8 int main()
     9 {
    10     int T, n, x, res;
    11     scanf("%d", &T);
    12     while(T--)
    13     {
    14         scanf("%d", &n); res = 0;
    15         for(int i = 1; i <= n; i++)
    16         {
    17             scanf("%d", &x);
    18             res ^= cal(x);
    19         }
    20         if(res) printf("first
    ");
    21         else printf("second
    ");
    22     }
    23 }

    题目够简单吗

    签到题,读入然后判断数组里面有没有1就可以了

     1 #include <stdio.h>
     2 int main()
     3 {
     4     int T, n, flag;
     5     while(scanf("%d", &T) != EOF)
     6     {
     7         while(T--)
     8         {
     9             scanf("%d", &n);
    10             flag = 0;
    11             int x;
    12             for(int i = 1; i <= n; i++)
    13             {
    14                 scanf("%d", &x);
    15                 if(x) flag = 1;
    16             }
    17             if(flag) printf("hard
    ");
    18             else printf("easy
    ");
    19         }
    20         
    21     }
    22 }

    推恩令

    又是来自大三学长的防Ak题,总的思想是二分。

    首先我们对题目分析后,我们可以将题目转化为有一个全为0的数列,第i我们可以把数列连续颜色的地方变成i然后问我们有多少种方法可以让原始数列变成输入的数列。

     1 #include <stdio.h>
     2 typedef long long ll;
     3 ll ans[509][509];
     4 const ll MOD = 292929;
     5 int a[509];
     6 void init(int n)
     7 {
     8     for(int i = 1; i <= n; i++)
     9         for(int j = i; j <= n; j++)
    10         ans[i][j] = -1;
    11 }
    12 ll dfs(int l, int r)
    13 {
    14     if(l>r) return 1;
    15     if(ans[l][r]!=-1) return ans[l][r];
    16     ll lans = 0, rans = 0;
    17     int pos = l, minn = a[l];
    18     for(int i = l+1; i <= r; i++)
    19     if(a[i] < minn)
    20     {
    21         minn = a[i]; pos = i;
    22     }
    23     for(int i = l; i <= pos; i++)
    24     lans = (lans + dfs(l,i-1) * dfs(i, pos-1) % MOD) % MOD;
    25     
    26     for(int i = pos+1; i <= r+1; i++)
    27     rans = (rans + dfs(pos+1, i-1) * dfs(i, r) % MOD) % MOD;
    28     
    29 //    printf("%d %d --- %lld %lld
    ", l, r, lans * rans + 1);
    30     return ans[l][r] = lans * rans % MOD; 
    31 }
    32 int main()
    33 {
    34     int T, n;
    35     scanf("%d", &T);
    36     while(T--)
    37     {
    38         scanf("%d", &n);
    39         init(n);
    40         for(int i = 1; i <= n; i++) scanf("%d", a+i);
    41         printf("%lld
    ", dfs(1, n));
    42     }
    43 }

            

    五等分的ACM

    题意模拟就可以了

     1 #include <stdio.h>
     2 int cal(int n)
     3 {
     4     int res = 0;
     5     while(n)
     6     {
     7         int tmp = n % 10;
     8         res += tmp * tmp * tmp  * tmp * tmp;
     9         n /= 10;
    10     }
    11     return res;
    12 }
    13 int main()
    14 {
    15     int T, n;
    16     scanf("%d", &T);
    17     while(T--)
    18     {
    19         scanf("%d", &n);
    20         if(n==cal(n)) printf("YES
    ");
    21         else printf("NO
    ");
    22     }
    23 }

    找找zyh

    分析几个样例

    我们定义numz , numy , numh 为以z y h结尾的前缀的当前出现次数

    那么最终的答案就是numh

     转移方程也很好理解, 分别是

     当当前字符为  z    时 Numz++;

     当当前字符为  y   时 numy += numz

     当当前字符为  h  时 numh += numy

                                          

    字符判断


    对于这三个样例  我们可以观察到如果用涂色法去涂这几个字母,A需要两次, B需要三次, C需要一次 (需要全部涂满)。

    涂色法可以用dfs处理

    需要特殊处理的是,在读入后要在周围添一圈留白,不然可能出现留白需要涂多次的情况,这个我们可以在读入的时候就预留出空间。

     1 #include <stdio.h>
     2 #include <cstring>
     3 char s[50][50] = {0};
     4 int move[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
     5 void dfs(int x, int y)
     6 {
     7     s[x][y] = '*';
     8     int tx, ty;
     9     for(int i = 0; i < 4; i++)
    10     {
    11         tx = x + move[i][0];
    12         ty = y + move[i][1];
    13         if(tx<0 || tx>49 || ty<0 || ty>49) continue;
    14         if(s[tx][ty]=='*') continue;
    15     //    printf("goto %d %d
    ", tx, ty);
    16         dfs(tx, ty);
    17     }
    18 }
    19 int main()
    20 {
    21     
    22     int time = 0, n;
    23     while(gets(s[1]) != NULL)
    24     {
    25         time = 0;
    26         if(strlen(s[1]) == 0) continue;
    27         n = 1;
    28         for(int i = 2; ; i++)
    29         {
    30             gets(s[i]);
    31             if(strlen(s[i])==0) break;
    32             n++;
    33         }
    34         
    35     //    for(int i = 1; i <= n; i++)
    36     //    puts(s[i]);
    37         
    38         for(int i = 0; i <= 49; i++)
    39             for(int j = 0; j <= 49; j++)
    40             {
    41                 if(s[i][j]!='*') 
    42                 {
    43                     dfs(i, j);
    44                     time++;
    45                 }
    46             }
    47             
    48     //    printf("%d
    ", time);
    49             
    50         if(time==1) printf("C
    ");
    51         else if(time==2) printf("A
    ");
    52         else printf("B
    ");
    53             
    54         memset(s, 0, sizeof(s));
    55     }
    56     return 0;
    57 }

    足球经理

    利用二维数组读入后,我们对于每一个队暴力模拟,计算分数就可以了

    计算完分数判断最大值,然后看有没有两个队分数一样就可以

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 using namespace std;
     5 int res[120][120];
     6 struct node
     7 {
     8     int score, id;
     9     bool operator < (struct node a)
    10     {
    11         return score > a.score;
    12     }
    13 }a[120];
    14 
    15 int main()
    16 {
    17     int T, n;
    18     while(scanf("%d", &T) != EOF)
    19     {
    20         while(T--)
    21         {
    22             scanf("%d", &n);
    23             for(int i = 1; i <= n; i++)
    24                 for(int j = 1; j <= n; j++)
    25                 scanf("%d", &res[i][j]);
    26             
    27             for(int i = 1; i <= n; i++)
    28             {
    29                 a[i].id = i;
    30                 a[i].score = 0;
    31                 for(int j = 1; j <= n; j++)
    32                 {
    33                     if(i==j) continue;
    34                     if(res[i][j] > res[j][i]) a[i].score += 3;
    35                     else if(res[i][j]==res[j][i]) a[i].score += 1;
    36                 }
    37             }
    38             a[n+1].score = -1;
    39             sort(a+1, a+1+n);
    40             if(a[1].score != a[2].score) printf("%d
    ", a[1].id);
    41             else printf("yep!
    ");
    42         }
    43     }
    44     
    45 }

            

  • 相关阅读:
    八十五:redis之redis的事物、发布和订阅操作 (2019-11-18 22:54)
    八十四:redis之redis的集合、哈希操作
    八十三:redis之redis的字符串、过期时间、列表操作
    八十三:redis之redis的使用场景和安装
    八十二:memcached之python操作memcached
    八十一:memcached之telnet操作memcached
    八十:memcached之安装与参数
    MySQL篇之Navicat可视化工具
    MySQL数据库篇之多表查询
    MySQL数据库篇之单表查询
  • 原文地址:https://www.cnblogs.com/loenvom/p/12036606.html
Copyright © 2020-2023  润新知