A 重合次数 (2023/5/1)
问题描述
在同一天中, 从上午 6 点 13 分 22 秒到下午 14 点 36 分 20 秒, 钟表上的 分针和秒针一共重合了多少次?
注意时针、分针、秒针都围绕中心敳匀速运动。
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一 个整数, 在提交答案时只填写这个整数, 填写多余的内容将无法得分。
运行限制
- 最大运行时间:1s
- 最大运行内存: 512M
public static void main(String[] args) {
// TODO Auto-generated method stub
int h = 6;
int m = 13 ;
int s = 22;
int count =0;
while(true) {
if (m==s && m!=59 && s!=59) {
count++;
}
s++;
if (s==60) {
s=0;
m++;
}
if (m==60) {
m=0;
h++;
}
if (h==14 && m==36 && s==20) {
break;
}
}
System.out.println(count);
}
思路: 分针和秒针 代表 电子表中分和秒的数值相同,但是要注意 在59分59秒开始,分针和秒针重合 与 下一个小时中0分0秒重合是相同的一次重合 所以在代码中 加了
m!=59 && s!=59
确保不会计算两次
B 数数(2023/5/1)
问题描述
任何一个大于 1 的正整数都能被分解为若干个质数相乘, 比如 28=2×2×728=2×2×7 被分解为了三个质数相乘。请问在区间 [2333333, 23333333] 中有多少个正整数 可以被分解为 12 个质数相乘?
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一 个整数, 在提交答案时只填写这个整数, 填写多余的内容将无法得分。
运行限制
- 最大运行时间:1s
- 最大运行内存: 512M
public static void main(String[] args) {
int start = 2333333;
int end = 23333333;
int count=0;
int[] data = new int [end+1];
for (int i = 1; i <= end; i++) {
int temp = i;
for (int j = 2; j <= Math.sqrt(i); j++) {
if(temp%j==0){
temp=temp/j;
data[i]=data[temp]+data[j];
break;
}
}
if (data[i]==0) {
data[i]=1;
}
if (data[i]==12 && i>2333333) {
System.out.println("data["+i+"]:"+data[i]);
count++;
}
}
System.out.println(count);
}
思路:这道题用了应该是动态规划的思路做
example: A = 质数* B 那么 B = 质数*C 。。。。 直到 被分解的两个数都是质数
加入代码的example:
28 = 2 * 14
那么 data[28] = data[2] + data[14]
因为2是质数,所以data[2] = 1
分解28 就可以 把问题化小 变成 分解 14
14 = 2 * 7 在这一步 因为 2 和 7 都是 质数,所以 data[2] + data[7]=2
所以我们就是不断把问题化小,而且符合动态规划的特点,所以这道题我尝试用动态规划的思路做
ps(我理解的动态规划):
- 大问题可以分解小问题
- 每个小问题都可能会被后面的大问题所运用到这个小问题的结果
- 用空间换时间,即我们先把这个小问题解决,用部分空间储存,在下一次被用到就可以直接拿到结果
这道题还是相当有趣的,但是我还是多了好久,填空题感觉暴力的可能性不是很高,还是需要分下下问题
C 左移右移
问题描述
小蓝有一个长度为 NN 的数组, 初始时从左到右依次是 1,2,3,…N1,2,3,…N 。
之后小蓝对这个数组进行了 MM 次操作, 每次操作可能是以下 2 种之一:
左移 xx, 即把 xx 移动到最左边。
右移 xx, 即把 xx 移动到最右边。
请你回答经过 MM 次操作之后, 数组从左到右每个数是多少?
输入格式
第一行包含 2 个整数, NN 和 MM 。
以下 MM 行每行一个操作, 其中 “L xx "表示左移 x,"Rxx,"Rx "表示右移 xx 。
输出格式
输出 NN 个数, 代表操作后的数组。
样例输入
5 3 L 3 L 2 R 1
样例输出
2 3 4 5 1
样例说明
样例中的数组变化如下:
[1,2,3,4,5]→[3,1,2,4,5]→[2,3,1,4,5]→[2,3,4,5,1][1,2,3,4,5]→[3,1,2,4,5]→[2,3,1,4,5]→[2,3,4,5,1]
评测用例规模与约定
对于 50%50% 的评测用例, 1≤N,M≤100001≤N,M≤10000.
对于 100%100% 的评测用例, 1≤N,M≤200000,1≤x≤N1≤N,M≤200000,1≤x≤N.
运行限制
- 最大运行时间:3s
- 最大运行内存: 512M
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int N = scan.nextInt();
int M = scan.nextInt();
LinkedHashMap<Integer, String> linkedHashMap = new LinkedHashMap<>();
for (int i = 0; i < M; i++) {
String op = scan.next();
int data = scan.nextInt();
if (linkedHashMap.containsKey(data)) {
linkedHashMap.remove(data);
}
linkedHashMap.put(data, op);
}
LinkedList<Integer> left = new LinkedList<>();
LinkedList<Integer> mid = new LinkedList<>();
LinkedList<Integer> right = new LinkedList<>();
for(Map.Entry<Integer, String> entry : linkedHashMap.entrySet()) {
if (entry.getValue().equals("L")) {
left.addFirst(entry.getKey());
}
else {
right.addLast(entry.getKey());
}
}
for (int i = 1; i <= N; i++) {
if (!linkedHashMap.containsKey(i)) {
mid.addLast(i);
}
}
for(int i : left) System.out.print(i+" ");
for(int i : mid) System.out.print(i+" ");
for(int i : right) System.out.print(i+" ");
}
思路: 问题用暴力非常简单,但是时间肯定是不够的
经过分析可以发现,左移的数可以是在左边的,右移的数肯定是在右边的,没有移动过的数一定是在中间的
在分析下又又发现,一个数可能会被移动好几次,但是无所谓,以最后一次为准就行
所以在这道题中我用到的容器有LinkedList 和 LinkedHashMap
LinkedHashMAp 是用来记录左右移动的操作数的,因为要检查这个数是否之前操作过,所以要有快速检索的功能,并且还要按照操作顺序来左右移动数,所以LinkedHashMap是最适合的
LinkedList 是来储存left mid right 三个部分的数据,因为是双向链表,所以left的话可以addFirst() , right 的话就可以addLast()。
这两个容器我也是刚了解,我应该会再写一篇答辩文章来记录下这些容器