T1 小美的因子数量
image-20260314102158293
image-20260314102203440
一个正整数的因子个数为奇数,当且仅当它是 完全平方数
因数通常是成对出现的,只有当 d = n/d
时,这一对因子才会合并为一个,从而使总数变成奇数。而 d = n/d 意味着
n = d2,即
n 是一个完全平方数(如 1, 4,
9, 16…)。
因此,题目要求的区间 [l, r]
内因子数量为奇数的数的个数,等价于问:区间 [l, r]
内有多少个完全平方数?
那么,计算区间 [l, r]
内完全平方数的个数,可以用 前缀和 的思想:
- 1 到 r 之间有多少完全平方数
- 计算 1 到 l−1 之间有多少个完全平方数
- 相减
1 2 3 4 5 6 7 8 9 10 11
| public static void main(String[] args) { Scanner in = new Scanner(System.in);
long l = in.nextLong(); long r = in.nextLong();
long countR = (long) Math.floor(Math.sqrt(r)); long countL = (long) Math.floor(Math.sqrt(l - 1));
System.out.println(countR - countL); }
|
T2 超级斐波那契数列
image-20260314102142204
image-20260314102147724
这题不会
image-20260314105142031
当查询次数 q
很大,且每次查询的范围固定,千万不要在查询循环里写复杂的逻辑。应该先花
O(N) 时间把所有可能的答案算出来存进数组,查询时直接 O(1) 读取。
在进行 (A - B) % MOD 时,如果
A < B,结果会变成负数。在 Java/C++ 中,必须写成
(A - B + MOD) % MOD 来保证结果落在 [0,MOD−1]
之间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| public static void main(String[] args) { Scanner sc = new Scanner(System.in); int k = sc.nextInt(); int q = sc.nextInt();
long MOD = 1000000007L; int MAX_X = 1000000;
long[] s = new long[MAX_X + 1]; long[] sum = new long[MAX_X + 1];
for (int i = 0; i <= MAX_X; i++){ if (i <= k){ s[i] = 1; }else{ long sum_c = sum[i - 1]; long sum_kc = sum[i - k - 1];
s[i] = (sum_c - sum_kc + MOD) % MOD; }
sum[i] = (sum[i - 1] + s[i]) % MOD; }
StringBuilder sb = new StringBuilder(); for (int i = 0; i < q; i++) { int x = sc.nextInt(); sb.append(s[x]).append("\n"); } System.out.print(sb.toString()); }
|
T3 最大节点权值
image-20260314102921534
image-20260314102929676
image-20260314102935664
不会
逆向并查集
从所有操作结束后的最终状态开始,倒着向前处理操作,并查集擅长加边,随着加边,节点的度数会增加,权值也会随之增加。
步骤:
记录初始状态:
读入所有的边和所有的操作。
确定最终度数:
计算出所有操作执行完毕后,每个节点剩余的度数。
初始化权值:
计算最终状态下每个节点的权值:Valuei=最终度数i+i。
建立初始并查集:
逆向处理操作: 从最后一个操作 q
开始向前遍历:
最后将结果逆序输出。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
| package 笔试面试题.美团.t3;
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.security.interfaces.EdECKey; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer;
public class Main {
static class Edge { int u, v; boolean deleted = false; Edge(int u, int v) { this.u = u; this.v = v; } }
static class Op { int type, x; Op(int type, int x) { this.type = type; this.x = x; } }
static int[] parent; static long[] maxVal; static long[] currentVal; static int[] degree;
static int find(int i){ if(parent[i] == i){ return i; }
return parent[i] = find(parent[i]); }
static void union(int i, int j){ int p1 = find(i); int p2 = find(j); if(p1 != p2){ parent[p1] = p2; maxVal[p2] = Math.max(maxVal[p2], maxVal[p1]); } }
public static void main(String[] args) throws IOException { FastReader fr = new FastReader(); PrintWriter out = new PrintWriter(System.out);
int n = fr.nextInt(); int m = fr.nextInt(); int q = fr.nextInt();
Edge[] e = new Edge[m + 1]; int[] initDegree = new int[n + 1];
for(int i = 1; i <= m; i++){ e[i] = new Edge(i, fr.nextInt()); initDegree[e[i].u]++; initDegree[e[i].v]++; }
Op[] ops = new Op[q]; for (int i = 0; i < q; i++) { ops[i] = new Op(fr.nextInt(), fr.nextInt()); if (ops[i].type == 1) { e[ops[i].x].deleted = true; initDegree[e[ops[i].x].u]--; initDegree[e[ops[i].x].v]--; } }
parent = new int[n + 1]; maxVal = new long[n + 1]; currentVal = new long[n + 1]; for (int i = 1; i <= n; i++) { parent[i] = i; currentVal[i] = (long)initDegree[i] + i; maxVal[i] = currentVal[i]; }
for (int i = 1; i <= m; i++) { if(!e[i].deleted){ union(e[i].u, e[i].v); } }
List<Long> results = new ArrayList<>(); for (int i = q - 1; i >= 0; i--) { if(ops[i].type == 2){ results.add(maxVal[find(ops[i].x)]); }else{ Edge edge = e[ops[i].x]; currentVal[edge.u]++; currentVal[edge.v]--;
int rootU = find(edge.u); maxVal[rootU] = Math.max(maxVal[rootU], currentVal[edge.u]); int rootV = find(edge.v); maxVal[rootV] = Math.max(maxVal[rootV], currentVal[edge.v); union(edge.u, edge.v); } }
for (int i = results.size() - 1; i >= 0; i--) { out.println(results.get(i)); } out.flush(); }
static class FastReader { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st; String next() { while (st == null || !st.hasMoreElements()) { try { st = new StringTokenizer(br.readLine()); } catch (IOException e) { e.printStackTrace(); } } return st.nextToken(); } int nextInt() { return Integer.parseInt(next()); } } }
|