A:求余
在 C/C++/Java/Python 等语言中,使用 % 表示求余,请问 2021%20 的值是多少?
public class Main{
public static void main(String[] args) {
System.out.print(2021 % 20);
}
}
ans:1
B:双阶乘
一个正整数的双阶乘,表示不超过这个正整数且与它有相同奇偶性的所有正整数乘积。n 的双阶乘用 n!! 表示。
例如:
3!! = 3 × 1 = 3。
8!! = 8 × 6 × 4 × 2 = 384。
11!! = 11 × 9 × 7 × 5 × 3 × 1 = 10395。
请问,2021!! 的最后 5 位(这里指十进制位)是多少?
注意:2021!! = 2021 × 2019 × · · · × 5 × 3 × 1。
提示:建议使用计算机编程解决问题。
对100000求余
public class Main{
public static void main(String[] args) {
int ans = 1;
for(int i = 2021; i >= 1; i -= 2) {
ans = (ans * i) % 100000;
}
System.out.print(ans);
}
}
ans:59375
C:格点
问题描述
如果一个点 ( x , y ) 的两维坐标都是整数,即 x ∈ Z 且 y ∈ Z ,则称这个点为一个格点。
如果一个点 ( x , y ) 的两维坐标都是正数,即 x > 0且 y > 0 ,则称这个点在第一象限。
请问在第一象限的格点中,有多少个点 ( x , y ) 的两维坐标乘积不超过 2021,即 x ⋅ y ≤ 2021。
public class Main{
public static void main(String[] args) {
int cnt = 0;
for(int i = 1; i <= 2021; i++) {
for(int j = 1; j <= 2021; j++) {
if(i * j <= 2021)
cnt++;
}
}
System.out.print(cnt);
}
}
ans:15698
D:整数分解
问题描述
将 3 分解成两个正整数的和,有两种分解方法,分别是 3 = 1 + 2 和 3 = 2 + 1。注意顺序不同算不同的方法。
将 5 分解成三个正整数的和,有 6 种分解方法,它们是 1 + 1 + 3 = 1 + 2 + 2 = 1 + 3 + 1 = 2 + 1 + 2 = 2 + 2 + 1 = 3 + 1 + 1
请问,将 2021 分解成五个正整数的和,有多少种分解方法?
2021个苹果分成5堆,有顺序,排列组合问题,答案为C(4, 2020)
public class Main{
public static void main(String[] args) {
long ans = 1;
for(int i = 2020, j = 1; j <= 4; j++, i--) {
ans = (ans * i) / j;
}
System.out.print(ans);
}
}
ans:691677274345
E:城邦
问题描述
小蓝国是一个水上王国,有 2021 个城邦,依次编号 1 到 2021 。在任意两个城邦之间,都有一座桥直接连接。
为了庆祝小蓝国的传统节日,小蓝国政府准备将一部分桥装饰起来。对于编号为 a 和 b 的两个城邦,它们之间的桥如果要装饰起来,需要的费用如下计算:找到 a 和 b 在十进制下所有不同的数位,将数位上的数字求和。
例如,编号为 2021 和 922 两个城邦之间,千位、百位和个位都不同,将这些数位上的数字加起来是 ( 2 + 0 + 1 ) + ( 0 + 9 + 2 ) = 14 。注意 922 922 922 没有千位,千位看成 0。
为了节约开支,小蓝国政府准备只装饰 2020 座桥,并且要保证从任意一个城邦到任意另一个城邦之间可以完全只通过装饰的桥到达。
请问,小蓝国政府至少要花多少费用才能完成装饰。
最小生成树模板(Kruskal)
public class Main{
static int n = 2021;
static int[] p = new int[2050];
static PriorityQueue<int[]> q = new PriorityQueue<>((o1, o2)->o1[2] - o2[2]);
public static void init() {
for(int i = 1; i <= 2021; i++) {
p[i] = i;
}
}
public static int f(int x) {
if(p[x] != x) p[x] = f(p[x]);
return p[x];
}
public static void merge(int a, int b) {
p[f(a)] = f(b);
}
public static void main(String[] args) {
init();
int ans = 0;
for(int i = 1; i <= 2021; i++) {
for(int j = i + 1; j <= 2021; j++) {
q.add(new int[]{i, j, getV(i, j)});
}
}
for(int i = 0; i < n - 1;) {
int[] e = q.poll();
int a = e[0], b = e[1], v = e[2];
if(f(a) != f(b)) {
merge(a, b);
i++;
ans += v;
}
}
System.out.print(ans);
}
public static int getV(int a, int b) {
int cnt = 0;
while(a > 0 && b > 0) {
int x = a % 10, y = b % 10;
if(x != y) {
cnt += (x + y);
}
a /= 10;
b /= 10;
}
while(a > 0) {
cnt += a % 10;
a /= 10;
}
while(b > 0) {
cnt += b % 10;
b /= 10;
}
return cnt;
}
}
ans:4046
F 特殊年份
问题描述
今年是 2021 年, 2021 这个数字非常特殊,它的千位和十位相等,个位比百位大 1 ,我们称满足这样条件的年份为特殊年份。
输入 5 个年份,请计算这里面有多少个特殊年份。
输入格式
输入 5 行,每行一个 4 位十进制数(数值范围为 1000 至 9999 ),表示一个年份。
输出格式
输出一个整数,表示输入的 5 个年份中有多少个特殊年份。
测试样例1
Input:
2019
2021
1920
2120
9899
Output:
2
Explanation:
2021 和 9899 是特殊年份,其它不是特殊年份。
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int cnt = 0;
for(int i = 0; i < 5; i++) {
String s = sc.next();
if(s.charAt(0) == s.charAt(2) && s.charAt(3) == s.charAt(1) + 1)
cnt++;
}
System.out.print(cnt);
}
}
G:小平方
问题描述
小蓝发现,对于一个正整数 n 和一个小于 n 的正整数 v,将 v 平方后对 n 取余可能小于 n 的一半,也可能大于等于 n 的一半。
请问,在 1 到 n − 1 中,有多少个数平方后除以 n 的余数小于 n 的一半。
例如,当 n = 4 时, 1 , 2 , 3 的平方除以 4 的余数都小于 4 的一半。
又如,当 n = 5 时, 1 , 4 的平方除以 5 的余数都是 1 ,小于 5 的一半。而 2 , 3 的平方除以 5 的余数都是 4 ,大于等于 5 的一半。
评测用例规模与约定
对于所有评测用例, 1 ≤ n ≤ 10000 1 ≤ n ≤ 10000 1≤n≤10000。
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int cnt = 0;
for(int i = 1; i < n; i++) {
if(((i * i) % n) * 2 < n) {
cnt++;
}
}
System.out.print(cnt);
}
}
H:完全平方数
问题描述
一个整数 a 是一个完全平方数,是指它是某一个整数的平方,即存在一个整数 b ,使得 a = b^2。
给定一个正整数 n ,请找到最小的正整数 x ,使得它们的乘积是一个完全平方数。
输入格式
输入一行包含一个正整数 n 。
测试样例1
Input:
12
Output:
3
测试样例2
Input:
15
Output:
15
Code
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
long n = sc.nextLong();
long ans = 1;
for(long i = 2; i <= n / i; i++) {
int cnt = 0;
while(n % i == 0) {
n /= i;
cnt++;
}
if(cnt % 2 != 0) ans *= i;
}
ans *= n;
System.out.print(ans);
}
}
I:负载均衡
问题描述
有 n 台计算机,第 i 台计算机的运算能力为 vi。
有一系列的任务被指派到各个计算机上,第 i 个任务在 ai 时刻分配,指定计算机编号为 bi ,耗时为 ci 且算力消耗为 di 。如果此任务成功分配,将立刻开始运行,期间持续占用 bi 号计算机 di 的算力,持续 ci 秒。
对于每次任务分配,如果计算机剩余的运算能力不足则输出 −1,并取消这次分配,否则输出分配完这个任务后这台计算机的剩余运算能力。
输入格式
输入的第一行包含两个整数 n , m ,分别表示计算机数目和要分配的任务数。
第二行包含 n 个整数 v 1 , v 2 , ⋯ ,vn,分别表示每个计算机的运算能力。
接下来 m 行每行 4 个整数 ai , bi , ci , di 意义如上所述。数据保证 ai 严格递增,即 ai < ai + 1。
输出格式
输出 m 行,每行包含一个数,对应每次任务分配的结果。
测试样例1
Input:
2 6
5 5
1 1 5 3
2 2 2 6
3 1 2 3
4 1 6 1
5 1 3 3
6 1 3 4
Output:
2
-1
-1
1
-1
0
Explanation:
时刻 1,第 1 个任务被分配到第 1 台计算机,耗时为 5 ,这个任务时刻 6会结束,占用计算机 1 的算力 3。
时刻 2,第 2 个任务需要的算力不足,所以分配失败了。
时刻 3,第 1 个计算机仍然正在计算第 1 个任务,剩余算力不足 3,所以失败。
时刻 4,第 1 个计算机仍然正在计算第 1 个任务,但剩余算力足够,分配后剩余算力 1。
时刻 5,第 1 个计算机仍然正在计算第 1, 4 个任务,剩余算力不足 4,失败。
时刻 6,第 1 个计算机仍然正在计算第 4 个任务,剩余算力足够,且恰好用完。
public class Main{
static int n, m, N = (int)2e5 + 10, a, b, c, d;
static int[] v = new int[N];
static List<PriorityQueue<int[]>> list = new ArrayList<>();
public static void main(String[] args) throws IOException {
n = nextInt();
m = nextInt();
for(int i = 1; i <= n; i++) {
v[i] = nextInt();
list.add(new PriorityQueue<>((o1, o2)->o1[0] - o2[0]));
}
while(m -- > 0) {
a = nextInt();
b = nextInt();
c = nextInt();
d = nextInt();
PriorityQueue<int[]> q = list.get(b - 1);
while(!q.isEmpty()) {
if(q.peek()[0] <= a) {
v[b] += q.poll()[1];
} else break;
}
if(v[b] >= d) {
q.add(new int[]{a + c, d});
v[b] -= d;
pw.println(v[b]);
} else pw.println(-1);
list.set(b - 1, q);
}
pw.flush();
}
static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter pw = new PrintWriter(System.out);
public static int nextInt() throws IOException {
cin.nextToken();
return (int)cin.nval;
}
}