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();
}
}