湖南理工学院2022年程序设计竞赛新生赛(同步赛)

湖南理工学院2022年程序设计竞赛新生赛(同步赛)

A lwy梦境中的斐波那契数列——诈骗签到题

根据题目描述,f(n) = f(n - 1) + n; 这个就是前n项和
==注意:==写的时候因为溢出问题wa了好几发,因为4399不是质数,不能用费马小定理求逆元,所以直接算,最后对结果取模即可
在有除法的时候,不能拆分取模运算{ (a%p / b%p) %p },所以在计算的过程中不能取模,只能是计算完之后再取模
最后是用python交的,太久没写了,手很生。

根据公式计算

/**
 * @author :Changersh
 * @date : 2023/4/23 15:09
 */

import java.io.*;
import java.util.*;
import java.lang.*;

public class Main {
    private static int P = 4399;
    private static long ans = 0, n;

    public static void main(String[] args) {
        n = sc.nextLong();
        ans = (1 + n) * n / 2;
        ans %= P;
        pw.println(ans);
        pw.close();
    }

}

B 你还会想起这道题吗

不要想得太复杂了,直接计算就行。
按下面代码的方法,直接判断 上、下、左、右、对角、反对角,是没有重复的

模拟

/**
 * @author :Changersh
 * @date : 2023/4/23 15:28
 */

import java.io.*;
import java.util.*;
import java.lang.*;

public class Main {
    private static int N = 100, n;
    private static int[][] g = new int[N][N];

    public static void main(String[] args) {
        n = sc.nextInt();
        int ans = 0;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                g[i][j] = sc.nextInt();
                if (i == 1 || j == 1 || i == n || j == n || i == j || i+j == n+1) 
                	ans += g[i][j];
            }
        }
        pw.println(ans);
        pw.close();
    }
}

C 你还会想起这道题吗(another version)

模拟题,我是按照大模拟写了,模拟层数,然后遍历每一层的所有元素

蛇形矩阵类模拟

/**
 * @author :Changersh
 * @date : 2023/4/23 15:55
 */

import java.io.*;
import java.util.*;
import java.lang.*;

public class Main {
    private static int N = 510, n;
    private static int[][] g = new int[N][N];

    public static void main(String[] args) {
        n = sc.nextInt();
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
                g[i][j] = sc.nextInt();

        int mx = 0, t = n / 2;
        for (int k = 0; k < t; k++) {
            int cnt = 0;
            for (int i = 1 + k; i <= n - k; i++) cnt += g[k + 1][i];
            for (int i = 1 + k + 1; i <= n - k; i++) cnt += g[i][k + 1];

            for (int i = 1 + k + 1; i <= n - k; i++) cnt += g[i][n - k];
            for (int i = 1 + k + 1; i <= n - k - 1; i++) cnt += g[n - k][i];
            mx = Math.max(mx, cnt);
        }
        if ((n & 1) == 1) mx = Math.max(mx, g[t+1][t+1]);

        pw.println(mx);
        pw.close();
    }
}

简单模拟

和上面的方法一样,也是计算某个点的层数,然后将它加到数组中,最后统计最大值
在输入时,根据横纵坐标计算层数,存入对应的数组: 对于下标(i, j) 它距离最外层的距离是:min(i, j, n - i + 1, n - j + 1)
也就是与 0 和 n+1 做差。

const int N=502;
int a[N][N];
int w[N];
int main()
{
    int n;
    scanf("%d",&n);

    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            scanf("%d",&a[i][j]);
            int ans=min({i,j,n-i+1,n-j+1});
            w[ans]+=a[i][j];   
        }
    }

    int res=0;
    for(int i=1;i<=n;i++)
    {
        res=max(res,w[i]);
    }
    printf("%d\n",res);
}

D 农场大户

用map存储小号的每种物品的数量,然后根据给出的价格卖出
考试的时候看着m比n大很多,以为会有重复数据,就又用了一个map存储价格,看到标程发现不用。
注意:1. 用long 2. 有可能m中的物品在小号n中不存在,java的hashmap使用getOrDefault() 返回个默认值,以免报错

HashMap

/**
 * @author :Changersh
 * @date : 2023/4/23 16:32
 */

import java.io.*;
import java.util.*;
import java.lang.*;

public class Main {
    private static int N = 1010, n, m, z;
    private static HashMap<String, Long> nm = new HashMap<>();
    private static HashMap<String, Long> ve = new HashMap<>();

    public static void main(String[] args) {
        n = sc.nextInt(); // sub num
        m = sc.nextInt(); // value num
        // name + num
        for (int k = 0; k < n; k++) {
            z = sc.nextInt(); // item kinds
            for (int i = 0; i < z; i++) {
                String s = sc.next();
                int h = sc.nextInt();
                nm.put(s, nm.getOrDefault(s, 0L) + h);
            }
        }
        // name + value
        for (int i = 0; i < m; i++) {
            String s = sc.next();
            long h = sc.nextInt();
            ve.put(s, h);
        }
        long ans = 0;
        Set<String> ks = ve.keySet();
        for (String s : ks) {
            long t = nm.getOrDefault(s, (long) -1);
            if (t != -1) ans += t * ve.get(s);
        }

        pw.println(ans);

        pw.close();
    }
}

E 一道较为复杂的签到题

本来输出的是800000000000000,这并不对,因为这是算的头发数量的和。算乘积的话按那个估计算的话应该根本输出不了
注意:算的是全世界所有人头发的乘积,这个世界有秃头,乘完还是 0.

恶心题

print(0)

F n车摆放问题

根据题意我们可以猜到,能放的棋子数最多是 min(n, m),所以,假设我们总是让 m 是小的。
那么,每一列都正好有一个棋子,我们要算的就是 n行中取 m行放棋子。
因为棋盘是
于是题目就转化成了组合数问题 A(n,m) = n! / (n-m)!

组合数学

import java.io.*;
import java.util.StringTokenizer;

/**
 * @author :Changersh
 * @date : 2023/4/23 16:58
 * 组合数学问题
 * 最大棋子数 = min(n, m)
 * 所以,我们假设 列m是小的,即所有列都正好放一个棋子,那么问题就转化成了n行中选m行放棋子
 * 变成组合数问题。A(n,m) = n! / (n-m)!
 */

public class Main {
    private static int N = 30, n, m, ans = 0, p;

    public static void main(String[] args) {
        n = sc.nextInt();
        m = sc.nextInt();

        // 要保证n >= m
        if (n < m) {
            int t = n;
            n = m;
            m = t;
        }
        pw.println(m);

        long up = jc(n);
        long dn = jc(n-m);

        long ans = up / dn;
        pw.println(ans);

        pw.close();
    }

    private static long jc(int x) {
        long ans = 1;
        for (int i = 1; i <= x; i++) ans *= i;
        return ans;
    }
}

H 皮卡丘的梦幻之旅(easy version)

典型的dp题目,m种物品,价值和恰好是n,每个物品的数量是无限的,这不是完全背包吗?!!
因为数据范围很小,m <= 3 就三种行走方法,最多走15步,每步有三种选择,最大也就是 3^15 的复杂度,可以过

爆搜

/**
 * @author :Changersh
 * @date : 2023/4/26 10:53
 */

import java.io.*;
import java.util.*;
import java.lang.*;

public class Main {
    private static int N = 220, n, m, ans = 0;
    private static int[] a = new int[N];
    public static void main(String[] args) {
        n = sc.nextInt();
        m = sc.nextInt();
        for (int i = 0; i < m; i++) a[i] = sc.nextInt();
        dfs(0);
        pw.println(ans);
        pw.close();
    }
    private static void dfs(int x) {
        if (x >= n) {
            if (x == n) ans++;
            return;
        }
        for (int i = 0; i < m; i++) {
            dfs(x + a[i]);
        }
    }
}

dp

完全背包

/**
 * @author :Changersh
 * @date : 2023/4/26 10:53
 */

import java.io.*;
import java.util.*;
import java.lang.*;

public class Main {
    private static int N = 20, n, m, ans = 0;
    private static int[] a = new int[N], f = new int[N];

    public static void main(String[] args) {
        n = sc.nextInt();
        m = sc.nextInt();
        for (int i = 1; i <= m; i++) a[i] = sc.nextInt();

        f[0] = 1;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                if (i >= a[j]) f[i] = f[i] + f[i - a[j]];
            }
        }

        pw.println(f[n]);
        pw.close();
    }
}

I 皮卡丘的梦幻之旅(middle version)

和上一题 dp 的代码基本上一样,只是数据范围扩大,并且需要取模了

完全背包

/**
 * @author :Changersh
 * @date : 2023/4/26 10:53
 */
import java.io.*;
import java.util.*;
import java.lang.*;

public class Main {
    private static int N = 5010, n, m, ans = 0, P = 998244353;
    private static int[] a = new int[N], f = new int[N];

    public static void main(String[] args) {
        n = sc.nextInt();
        m = sc.nextInt();
        for (int i = 1; i <= m; i++) a[i] = sc.nextInt();

        f[0] = 1;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                if (i >= a[j]) f[i] = (f[i] % P + f[i - a[j]] % P) % P;
            }
        }

        pw.println(f[n]);
        pw.close();
    }
}

K n个数的高精度乘法

虽然数很大,但结果是 mod 10000 的,所以只有最后四位是有效的,那么我们可以只取出最后四位计算即可,如果小于四位,全取出来。
每次乘完之后mod一下防止溢出

思维题

/**
 * @author :Changersh
 * @date : 2023/4/26 14:45
 * mod 10000,那么我们可以只取出最后四位计算即可,如果小于四位,全取出来
 */

import java.io.*;
import java.util.*;
import java.lang.*;

public class Main {
    private static int n, ans = 1, P = 10000, t;
    private static String s;
    private static char[] a;

    public static void main(String[] args) {
        n = sc.nextInt();
        for (int i = 0; i < n; i++) {
            s = sc.next();
            if (s.length() <= 4)
                t = Integer.parseInt(s);
            else
                t = Integer.parseInt(s.substring(s.length() - 4));
            ans *= t;
            ans %= P;
        }
        
        pw.println(ans);
        pw.close();
    }
}

L 轩哥的疑惑

签到题,答案是比赛题目的总数
(看这个题目被绕了半天,真讨厌)

print(14)

M 集!挡!波!

分析题目可得,不可能输的,只有win 和 draw 两种可能
我们要赢,只需要在对手 J、D 的时候也 J 攒能量
这时,我们已经可以发动技能了,只要对手是 J ,就不能防御,我们直接 B,干掉他,取得胜利。

按照上面的模拟即可

贪心

/**
 * @author :Changersh
 * @date : 2023/4/26 10:09
 */

import java.io.*;
import java.util.*;
import java.lang.*;

public class Main {
    private static int N = 1010, n;
    private static char[] a;
    public static void main(String[] args) {
        n = sc.nextInt();
        a = sc.next().toCharArray();
        int t = 0;
        for (int i = 0; i < n; i++) {
            if ((a[i] == 'J' || a[i] == 'D') && t == 0) t = 1;
            else if (t == 1 && a[i] == 'J') {
                pw.println("win");
                pw.close();
            }
        }
        pw.println("draw");
        pw.close();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值