首页 > 其他分享 >嘉应学院第一届新生娱乐赛第一场题解

嘉应学院第一届新生娱乐赛第一场题解

时间:2024-09-16 16:26:33浏览次数:1  
标签:gcd 奇数 int 题解 嘉应学院 偶数 第一场 printf include

A

一道简单的语法题,直接输出"hello nowcoder"即可。

代码

#include <stdio.h>

int main()
{
    printf("hello nowcoder");
}

B

也是一道语法题,考察分支结构。根据题意进行判断输出即可。

代码

#include <stdio.h>

int main()
{
    int a, b;
    scanf("%d %d", &a, &b);
    
    if (a > b) {
        printf(">");
    }
    else if (a < b) {
        printf("<");
    } 
    else {
        printf("=");
    }
}

C

一道考察循环结构的语法题,枚举1~n,对于每个数,进行mod10运算,获取最低位上的数进行判断是否是目标数,如果是则答案加一。

代码

#include <stdio.h>

int count(int x, int t)
{
    int res = 0;
    while (x)
    {
        if (x % 10 == t) res ++;
        x /= 10;
    }
    return res;
}

int main()
{
    int n, x;
    scanf("%d %d", &n, &x);
    
    int ans = 0;
    for (int i = 1; i <= n; i ++)
    {
        ans += count(i, x);
    }
    
    printf("%d", ans);
    
    return 0;
}

D

一道很不错的题,解法不唯一,纯用作考察循环结构也行。 以下我的解析:
根据题意,可以有如下规律:

\[\begin{aligned} &1 \\ &2 \quad 2 \\ &3\quad3\quad3 \\ &4\quad4\quad4\quad4 \\ &{\cdots} \end{aligned} \]

发放的金币总量是

\[total = 1 + 2^2 + 3^2 + {\cdots} + d^2 + k,\qquad k<(d+1)^2 \]

发放天数是

\[day=1+2+3+{\cdots}+d+k^{'} = \frac{(1+d)*d}{2}+k^{'}, \qquad k^{'}<d+1 \]

由此可见我们只需循环枚举金币数n,每次减去天数k和金币数加上k*k,当剩余天数k>=n时特殊处理,答案加上n*k。

代码

#include <stdio.h>

int main()
{
    int n;
    scanf("%d", &n);
    
    int total = 0, k = 1;
    while (n >= k)
    {
        total += k * k;
        n -= k;
        k ++;
    }
    total += n * k;
    
    printf("%d", total);
    
    return 0;
}

但我们可以注意到在\(day = \frac{(1 + d)*d}{2} {\le}n\)时,我们是做一个\(\sum_{i=1}^{d}i^2=\frac{d*(d+1)*(2*d+1)}{6}\),做完这个求和再特殊处理k即可,看如下代码,注意公式可能超过int范围。

#include <stdio.h>
#include <math.h>

#define ll long long

int main()
{
    int n;
    scanf("%d", &n);
    
    ll d = (sqrt(1 + 8 * n) - 1) / 2; // 求根公式
    int total = d * (d + 1) * (2 * d + 1) / 6;
    total += (n - d * (d + 1) / 2) * (d + 1);
    
    printf("%d", total);
    
    return 0;
}

一道不错的算法入门,主要是思考如何用算法优化到接近\(O(1)\)

E

一个算法入门题吧,当然只跑循环枚举也能解题,这里主要引入一下欧几里得算法(gcd),不细讲,大家自行查找资料。
题意提取就是寻找三个数的最小公倍数。
gcd算法就是求两个数的最大公因数,而可知最小公倍数=两个数的乘积除以最大公约数。这题就明了了,先求前两个数的最小公倍数,再和最后一个求最小公倍数。

代码

#include <stdio.h>

int gcd(int a, int b)
{
    return b ? gcd(b, a % b) : a; // 辗转相除法,翁恺貌似讲过,大家翻翻视频
}

int main()
{
    int a, b, c;
    scanf("%d %d %d", &a, &b, &c);
    
    int num = a * b / gcd(a, b);
    int res = num * c / gcd(num, c);
    
    printf("%d", res);
}

再贴一道暴力跑循环的题解,仅适用此题

#include <stdio.h>

int main()
{
    int a, b, c;
    scanf("%d %d %d", &a, &b, &c);
    
    int res = 0;
    for (int i = 1; i <= a * b * c; i ++)
        if (i % a == 0 && i % b == 0 && i % c == 0)
        {
            res = i;
            break;
        }

    printf("%d", res);
    return 0;
}

F

题目大意是告诉一个等差数列的首项和公差,问你在第\(l\)和\(r\)项之间是奇数多、偶数多还是一样多。
根据最基本的数值计算:

\[奇数+奇数=偶数\\ 偶数+偶数=偶数\\ 奇数+偶数=奇数\\ 偶数*偶数=偶数 奇数*偶数=偶数\\ 奇数*奇数=奇数\\ \]

由此,公差为偶数时,首项为奇数则数列都是奇数,首项为偶数则数列都是偶数;公差为奇数时,数列都是一个奇偶交叉的数列,这时就考虑询问的区间,如果询问区间个数是一个偶数,则区间内奇偶一定是相同的;如果询问的个数是一个奇数,思考第\(l\)项是什么数,因为奇数个数数列区间首项和尾项一定是相同的性质,每两个一组,则多出的那个决定了答案。

\[奇偶奇偶奇偶奇偶奇\\ 偶奇偶奇偶奇偶奇偶\\ \]

让数列从1开始标号,可以发现一个性质,首项是奇数的数列,偶数项一定偶数,奇数项一定是奇数;首项是偶数的数列,偶数项一定奇数,奇数项一定是偶数,到此,我们可以根据询问的区间首项\(l\)来得出答案。

代码

#include <stdio.h>

#define ll long long

int a, k, q;

int main()
{
    scanf("%d %d %d", &a, &k, &q);
    
    a %= 2, k %= 2; // 简化,1是奇数,0是偶数
    
    while (q --)
    {
        int l, r;
        scanf("%d %d", &l, &r);
        
        if (!k) // 公差为偶数时
        {
            if (a) {
                printf("1\n");
            } else {
                printf("-1\n");
            }
        } 
        else 
        {
            if ((r - l) % 2) { // 区间个数是偶数
                printf("0\n");
            } else if ((a + l) % 2) { // 根据首项和l的奇偶性判断
                printf("-1\n");
            } else {
                printf("1\n");
            }
        }
    }
    
    return 0;
}

G

一个经典的贪心题,引入算法贪心。
贪心算法,如字面意思,在每一步操作都进行最贪婪步骤,意图以最快或最优达成目标。
题目意思是从0开始+1或+3到达目标点,其中+3不能连续进行,问最小步骤数。显然的,要最快,必然是贪婪做最多的+3操作,快速靠近目标点,然后再用+1补上。但+3不能连续操作,那么就要中间插入+1操作,必然贪婪的插入最少的+1操作,由此解法就明显了。

代码

#include <stdio.h>

#define ll long long

ll n;

int main()
{
    scanf("%d", &n);
    
    // 既然是保证+1间隔+3操作,就以这两个为一组,让总数mod4,恰好整除步数就是n/2
    if (n % 4 == 0) {
        printf("%lld", n / 4 * 2);
    } else if (n % 4 == 1 || n % 4 == 3) {
        printf("%lld", n / 4 * 2 + 1); // 差1或3,我们是可以一步到达的
    } else {
        printf("%lld", n / 4 * 2 + 2); // 差2,只能两次+1操作
    }
    
    return 0;
}

H

全场最难,思维题
mex和gcd的定义看题目,这里不细讲。
根据题目,首先处理特殊情况,全0下,答案必是0,因为gcd(0,0) = 0
思考

  • 当\(mex \ge 2\)时,此时区间内一定有0,1两个数,则gcd一定等于1,那么这时就要让mex值最大即可,mex最大的情况就是全数组都选。
  • 当\(mex=0\)时,答案一定为0,不用考虑gcd
  • 当\(mex=1\)时,区间一定有0,而选择的数越多,gcd数一定越小,所以要选最少的数,我们只需再选与0相邻的数。

代码

#include <stdio.h>
#include <stdbool.h>

#define ll long long

const int N = 1e5 + 10;

int n, res;
int a[N];
ll sum;
bool st[N];

int max(int a, int b)
{
    return a > b ? a : b;
}

int main()
{
    scanf("%d", &n);
    
    for (int i = 1; i <= n; i ++) 
    {
        scanf("%d", &a[i]);
        sum = sum + a[i];
        st[a[i]] = 1;
    }
    // 特殊判断全0的情况
    if (sum == 0) {
        printf("%d", 0);
        return 0;
    }
    
    // 找出全部数的mex
    while (st[res]) res ++;
    // 找0相邻的数,取一个最大。
    for (int i = 1; i <= n; i ++)
        if (a[i] == 0) {
            res = max(res, a[i - 1]);
            res = max(res, a[i + 1]);
        }
    
    printf("%d", res);
    
    return 0;
}

题解到此结束!

标签:gcd,奇数,int,题解,嘉应学院,偶数,第一场,printf,include
From: https://www.cnblogs.com/Natural-TLP/p/18416210

相关文章

  • [ARC096E] Everything on It 题解
    题目链接点击打开链接题目解法肯定考虑容斥钦定有\(a\)个数出现\(0\)次,有\(b\)个数出现恰好\(1\)次,其他\(n-a-b\)个数随便,容斥系数为\((-1)^{a+b}\)先给出方案数的表达式:\(\sum\limits_{a=0}^n\sum\limits_{b=0}^{n-a}(-1)^{a+b}2^{2^{n-a-b}}\binom{n}{a}\binom{......
  • 图:310.最小高度数, 题解
    310.最小高度树-力扣(LeetCode)参考题解:算法逻辑:算法的核心思路是逐层剪去叶子节点,直到剩下的节点是最小高度树的根。示例:假设有如下的树结构:0/\12/\34初始时,叶子节点是1、3和4,剪掉这些叶子节点后,树变成:0\2再次剪掉......
  • 【洛谷 P1216】[USACO1.5] [IOI1994]数字三角形 Number Triangles 题解(动态规划)
    [USACO1.5][IOI1994]数字三角形NumberTriangles题目描述观察下面的数字金字塔。写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以走到左下方的点也可以到达右下方的点。在上面的样例中,从的路径产生了最大权值。输入格式第一个行一个正整数......
  • 题解:P9938 [USACO21OPEN] Acowdemia II B
    首先根据每篇出版物构建一个资历比较矩阵\(g\),其中\(g_{a,b}=1\)表示研究员\(a\)比\(b\)资历更高。遍历每篇出版物,识别出第一个降序的名字,然后假定该名字之后的所有研究员资历都比当前名字对应的研究员资历高即可。代码:#include<bits/stdc++.h>usingnamespacestd;......
  • 题解:P9951 [USACO20FEB] Swapity Swap B
    奶牛的排列经过\(x\)次后会回到原来的位置,理解以下:\([a_1,a_2]\)的牛翻转两次就会回到原来的位置,\([b_1,b_2]\)的牛翻转两次也会回到原来的位置,所以原来奶牛的排列经过一定次数的旋转后一定会回到原来位置。我们只要先模拟得出多少次后第\(i\)位的奶牛会回到原来的位置,然后......
  • 题解:P9953 [USACO20OPEN] Social Distancing II B
    解决思路:根据奶牛的位置对数组进行排序。计算相邻健康奶牛和感染奶牛之间的最小距离。这个距离值减一用来估计感染传播的半径。(确保了感染奶牛之间的距离在当前半径下不会导致传播给其他健康奶牛。)遍历排序后的奶牛列表,找到每一段连续感染奶牛的区域,并计算这些区域中可能需要的......
  • 区间检测题解
    记录\(pre_i\)为\(a_i\)上一次出现的位置。每一次求\([L,R]\)范围内是否有相同的数即\(pre_L\)到\(pre_R\)中的最大值是否小于\(L\)。注意到\(pre_1\)到\(pre_{L-1}\)中最大数一定小于\(L\),所以求\([L,R]\)范围内是否有相同的数即\(pre_1\)到\(pre_R\)中的......
  • 题解:P9957 [USACO20DEC] Stuck in a Rut B
    由于\(x,y\leq10^9\),我们无法模拟每个时间段。因此,我们需要尝试判断两头牛何时会相交。一个重要的观察是,牛不能后退,所以两头牛发生碰撞的唯一方式是\(n[x]>e[x]\)且\(n[y]<e[y]\)。可以按牛的起始坐标进行排序,然后模拟这些碰撞。代码:#include<bits/stdc++.h>using......
  • 题解:P3113 [USACO14DEC] Marathon G
    用线段树维护子路径的长度和这条子路径上删除一个点能够减少的最大距离。那么,修改就修改线段树上对应位置的值,查询就求这一段子路径的距离和子路径上删除一个点能够减少的最大距离,两者相减即可得到答案。代码:#include<bits/stdc++.h>usingnamespacestd;typedefpair<int,in......
  • 题解:P10961 划分大理石
    设\(f_x\)表示拼成\(x\)后,当前的大理石最多还能剩下几块,不能拼成就是\(-1\)。状态转移(当前考虑的大理石价值为\(i\),有\(x\)块):\(f_j=x(f_j\ge0)\)本来就可以拼成,那么现在的大理石都可以剩下。\(f_j=f_{j-i}-1(f_j=-1,j\gei,f_{j-i}>0)\)本来不能拼成,但用了一块就能拼......