T1 质因数个数
思路:分解质因数,从2开始遍历,遇到一个质因数就cnt ++
,然后将n
中的这个质因数除干净,最后的n
如果大于1
,就说明这个数本身是质数或者有一个大于sqrt(n)
的质因数,需要最后再加一。
注意:需要开成long
类型
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
long n = sc.nextLong();
int cnt = 0;
for (long i = 2; i <= n / i; i ++) {
if (n % i == 0) {
while (n % i == 0) {
n /= i;
}
cnt ++;
}
}
if (n > 1) cnt ++;
System.out.print(cnt);
}
}
T2 数位排序
思路:重写小于号或者使用快排
- 方式1:有一个数据超内存(96分)
import java.util.*;
public class Main {
static class Num implements Comparable<Num>{
public int x;
public Num(int x) {
this.x = x;
}
@Override
public int compareTo(Num p) {
String s1 = x + "";
String s2 = p.x + "";
int sum1 = 0, sum2 = 0;
for (int i = 0; i < s1.length(); i ++) {
sum1 += s1.charAt(i) - '0';
}
for (int i = 0; i < s2.length(); i ++) {
sum2 += s2.charAt(i)- '0';
}
if (sum1 != sum2) return sum1 - sum2;
return x - p.x;
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(), m = sc.nextInt();
Num[] a = new Num[n];
for (int i = 0; i < n; i ++) {
a[i] = new Num(i + 1);
}
Arrays.sort(a);
System.out.print(a[m - 1].x);
}
}
- 方式2(100分)
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(), m = sc.nextInt();
Integer[] a = new Integer[n];
for (int i = 0; i < n; i ++) a[i] = i + 1;
Arrays.sort(a, new Comparator<Integer>() {
@Override
public int compare(Integer a, Integer b) {
String s1 = a + "";
String s2 = b + "";
int sum1 = 0, sum2 = 0;
for (int i = 0; i < s1.length(); i ++) {
sum1 += s1.charAt(i) - '0';
}
for (int i = 0; i < s2.length(); i ++) {
sum2 += s2.charAt(i)- '0';
}
if (sum1 != sum2) return sum1 - sum2;
return a - b;
}
});
System.out.print(a[m - 1]);
}
}
T3 蜂巢
错误做法(暴力宽搜TLE 2分):
import java.util.*;
public class Main {
static class Point {
public double x, y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
}
//偏移量
static double[] dx = {-1, -0.5, 0.5, 1, 0.5, -0.5}, dy = {0, 0.5, 0.5, 0, -0.5, -0.5};
static HashMap<Point, Integer> map = new HashMap<>();
public static int bfs(Point start, Point end) {
LinkedList<Point> queue = new LinkedList<Point>();
queue.add(start);
map.put(start, 0);
while (!queue.isEmpty()) {
Point t = queue.remove();
double x = t.x, y = t.y;
int dist = map.get(t);
for (int i = 0; i < 6; i ++) {
double a = x + dx[i], b = y + dy[i];
Point p = new Point(a, b);
if (map.containsKey(p)) continue;
if (a == end.x && b == end.y) {
return dist + 1;
}
queue.add(p);
map.put(p, dist + 1);
}
}
return -1;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int d1 = sc.nextInt(), p1 = sc.nextInt(), q1 = sc.nextInt();
int d2 = sc.nextInt(), p2 = sc.nextInt(), q2 = sc.nextInt();
//将相对坐标转换为笛卡尔坐标
double x1 = dx[d1] * p1 + dx[(d1 + 2) % 6] * q1;
double y1 = dy[d1] * p1 + dy[(d1 + 2) % 6] * q1;
double x2 = dx[d2] * p2 + dx[(d2 + 2) % 6] * q2;
double y2 = dy[d2] * p2 + dy[(d2 + 2) % 6] * q2;
Point start = new Point(x1, y1);
Point end = new Point(x2, y2);
System.out.print(bfs(start, end));
}
}
T5 重新排序
思路:多次询问,每次询问可能会有重复区间,利用差分操作,求出每个下标被查询的次数,将原素组最大的数放在查询次数最多的下标处,则再次查询结果最大
没有ac,可能有情况没考虑到(52分)
- 错误代码仅供参考:
import java.io.*;
import java.util.*;
public class Main {
static final int N = 100010;
static int[] a = new int[N]; // 差分数组,记录每个下标被查询的次数
static long[] sum1 = new long[N]; //前缀和
static long[] sum2 = new long[N]; //前缀和
static int[][] query = new int[N][2]; //记录查询
public static void insert(int l, int r, int c) {
a[l] += c;
a[r + 1] -= c;
}
static class Times implements Comparable<Times>{
public int times, index;
public Times(int times, int index) {
this.times = times;
this.index = index;
}
@Override
public int compareTo(Times p) {
return this.times - p.times;
}
}
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine().split(" ")[0]);
int[] s = new int[n]; //原数组
int[] new_s = new int[n]; //按照频率排序后的数组
String[] s1 = br.readLine().split(" ");
for (int i = 0; i < n; i ++) {
s[i] = Integer.parseInt(s1[i]);
if (i == 0) sum1[i] = s[i];//下标从0开始,无奈之举
else sum1[i] = sum1[i - 1] + s[i];
}
int q = Integer.parseInt(br.readLine().split(" ")[0]);
int res1 = 0;
int k1 = 0;
for (int i = 0; i < q; i ++){
String[] s2 = br.readLine().split(" ");
int l = Integer.parseInt(s2[0]) - 1;
int r = Integer.parseInt(s2[1]) - 1;
insert(l, r, 1);
if (l == 0) res1 += sum1[r];
else res1 += (sum1[r] - sum1[l - 1]); //原始查询结果
query[k1][0] = l;
query[k1][1] = r;
k1 ++;
}
//计算查询频率
for (int i = 1; i < n; i ++) {
if (i > 0) a[i] += a[i - 1];
}
Arrays.sort(s); //将原始数组从小到大排序
Times[] times = new Times[n];
for (int i = 0; i < n; i ++) {
times[i] = new Times(a[i], i);
}
Arrays.sort(times); //将查询频率带着下标排序
int k = 0;
//按照查询频率将原数组排序,查询最多的下标存放数组中的最大值
for (Times t : times) {
new_s[t.index] = s[k ++];
}
//求按照查询频率排序后数组的前缀和
for (int i = 0; i < n; i ++) {
if (i == 0) sum2[i] = new_s[i];
else sum2[i] += sum2[i - 1] + new_s[i];
}
//重新查询
int res2 = 0;
for (int i = 0; i < q; i ++) {
int l = query[i][0], r = query[i][1];
if (l == 0) res2 += sum2[r];
else res2 += (sum2[r] - sum2[l - 1]);
}
System.out.print(res2 - res1);
}
}
注:数组可以都开在main方法外,Arrasys.sort可以指定范围排序(get到的新知识点)
正规做法:统计每个位置被查询的次数同上,然后利用贪心:排序不等式,将查询次数数组升序排列,将原数组升序排列,两数组对应下标的数相乘再相加即可。查询的时候可以不用前缀和
- ac代码:
import java.io.*;
import java.util.*;
public class Main {
static int N = 100010;
static int[] a = new int[N];
static long[] s = new long[N];
static long[] g = new long[N];
static int n;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
n = Integer.parseInt(br.readLine().split(" ")[0]);
String[] v = br.readLine().split(" ");
for (int i = 1; i <= n; i ++) {
a[i] = Integer.parseInt(v[i - 1]);
s[i] = s[i-1] + a[i];
}
int m = Integer.parseInt(br.readLine());
long res1 = 0;
for (int i = 0; i < m; i++) {
v = br.readLine().split(" ");
int l = Integer.parseInt(v[0]);
int r = Integer.parseInt(v[1]);
g[l] ++;
g[r + 1] --;
res1 += s[r] - s[l - 1];
}
for (int i = 1; i <= n; i++) {
g[i] += g[i - 1];
}
long res2 = 0;
Arrays.sort(a);
Arrays.sort(g);
int pre = g.length - 1;
while (g[pre] != 0){
res2 += g[pre] * a[pre];
pre --;
}
System.out.println(res2 - res1);
}
}