专栏文章
P12254美丽区间题解
P12254题解参与者 7已保存评论 7
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 7 条
- 当前快照
- 1 份
- 快照标识符
- @mipeq40j
- 此快照首次捕获于
- 2025/12/03 10:47 3 个月前
- 此快照最后确认于
- 2025/12/03 10:47 3 个月前
题解:P12254 美丽区间
本蒟蒻第一次写题解,不喜勿喷。
思路
-
预处理每个数字所在的美丽区间。
-
输出答案。
实现方法:
1. 使用 while 循环计算每个美丽区间的左边界和右边界
-
我们可以定义一个 表示这是第几个美丽区间,每算完一个区间时, 加上一个 ,计算下一个区间。
-
因为题目要求的是 , 之间的差尽可能的小,所以第 个美丽区间的左边界可以直接等于上一个美丽区间的右边界(条件 2:),第 个美丽区间的右边界可以等于上一个美丽区间的左边界 (条件 3:)。
-
当 和 不满足条件 ()时,可以自增 , 直到满足条件 为止。
2. 每次读入 时,循环遍历每个美丽区间,当 在此美丽区间中时,即可输出此美丽区间的编号。
但是这样会 TLE 的。
为什么会这样呢?
原来是在读入中,每读入一个 后都要一个 for 循环来查找,导致超时。
那该怎么办呢?
答:用一个 数组存储第 个数字在哪个美丽区间中,每次找到美丽区间的左右边界( 和 数组),就循环一次记录 。
原来是在读入中,每读入一个 后都要一个 for 循环来查找,导致超时。
那该怎么办呢?
答:用一个 数组存储第 个数字在哪个美丽区间中,每次找到美丽区间的左右边界( 和 数组),就循环一次记录 。
AC Code:
- C++:
#include <bits/stdc++.h>
using namespace std;
int l[5000010],r[5000010],ans[5000010];
int k,t,n,cnt = 0;
signed main(){
scanf("%d%d",&k,&t);
//初始化
l[0] = 0,r[0] = 0;
while(r[cnt] < 1000000){
cnt++;
l[cnt] = r[cnt - 1] + 1;
r[cnt] = k + l[cnt];
while(__gcd(l[cnt],r[cnt]) > 1){ //这是个好东西
r[cnt]++;
}
for(int i = l[cnt];i <= r[cnt];i++){
ans[i] = cnt;
}
}
//直接输出
while(t--){
scanf("%d",&n);
printf("%d\n",ans[n]);
}
return 0;
}
- Java:
import java.util.Scanner;
public class Main {
static int[] l = new int[5000010];
static int[] r = new int[5000010];
static int[] ans = new int[5000010];
static int k, t, n, cnt = 0;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
k = sc.nextInt();
t = sc.nextInt();
// 初始化
l[0] = 0;
r[0] = 0;
while (r[cnt] < 1000000) {
cnt++;
l[cnt] = r[cnt - 1] + 1;
r[cnt] = k + l[cnt];
while (gcd(l[cnt], r[cnt]) > 1) { // 这是个好东西
r[cnt]++;
}
for (int i = l[cnt]; i <= r[cnt]; i++) {
ans[i] = cnt;
}
}
// 直接输出
while (t-- > 0) {
n = sc.nextInt();
System.out.println(ans[n]);
}
}
// 计算最大公约数
static int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
}
相关推荐
评论
共 7 条评论,欢迎与作者交流。
正在加载评论...