publicstaticvoidmain(String[] args){ Scanner scanner =newScanner(System.in); int[] square =newint[100]; for(int i =0; i != square.length;++i){ square[i]=(i +1)*(i +1); } int n = scanner.nextInt(); boolean flag =true; for(int i =0; i != square.length;++i){ int x = square[i]; int y = n - x; if(y < x)break; int index =Arrays.binarySearch(square, y); if(index <0)continue; flag =false; System.out.printf("%d %d\n", i +1, index +1); } if(flag)System.out.print("No Solution"); }
}
判断题
判断题的评判很简单,本题就要求你写个简单的程序帮助老师判题并统计学生们判断题的得分。
输入格式
输入在第一行给出两个不超过 100 的正整数 N 和 M,分别是学生人数和判断题数量。第二行给出 M 个不超过 5 的正整数,是每道题的满分值。第三行给出每道题对应的正确答案,0 代表“非”,1 代表“是”。随后 N 行,每行给出一个学生的解答。数字间均以空格分隔。
publicstaticvoidmain(String[] args)throwsIOException{ int n =read(); int m =read(); int[] scores =newint[m];// 每道题的分数 int[] answer =newint[m];// 每道题的正确答案 for(int i =0; i != m;++i){ scores[i]=read(); } for(int i =0; i != m;++i){ answer[i]=read(); } for(int i =0; i != n;++i){ int ans =0; for(int k =0; k != m;++k){ if(read()== answer[k]) ans += scores[k]; } System.out.println(ans); } }
staticintread()throwsIOException{ int result =0; int input =System.in.read(); do{ result =(result <<1)+(result <<3)+(input ^48); input =System.in.read(); }while(Character.isDigit(input)); return result; }
}
数列求和 - 加强版
给定某数字 A(1 <= A <= 9)以及非负整数 N(0 <= N <= 100000),求数列之和 S = A + AA + AAA + ⋯ + AA⋯A(N 个 A)。例如 A = 1, N = 3时,S = 1 + 11 + 111 = 123。
publicstaticvoidmain(String[] args){ Scanner scanner =newScanner(System.in); StringBuilder sb =newStringBuilder(); int a = scanner.nextInt(); int n = scanner.nextInt(); if(n ==0){ System.out.println(0); return; } int carry =0;// 进位 for(int c = n; c !=0;--c){ int value = carry + a * c; carry = value /10; sb.append(value %10); } if(carry !=0) sb.append(carry); // 算出来的结果是反着的,需要倒序输出 System.out.println(sb.reverse()); }
}
大炮打蚊子
现在,我们用大炮来打蚊子:蚊子分布在一个 M × N 格的二维平面上,每只蚊子占据一格。向该平面的任意位置发射炮弹,炮弹的杀伤范围如下示意:
1 2 3
O OXO O
其中,X 为炮弹落点中心,O 为紧靠中心的四个有杀伤力的格子范围。若蚊子被炮弹命中(位于 X 格),一击毙命,若仅被杀伤(位于 O 格),则损失一半的生命力。也就是说,一次命中或者两次杀伤均可消灭蚊子。现在给出蚊子的分布情况以及连续 k 发炮弹的落点,给出每炮消灭的蚊子数。
输入格式
第一行为两个不超过 20 的正整数 M 和 N,中间空一格,表示二维平面有 M 行、N 列。
接下来M行,每行有 N 个 0 或者 # 字符,其中#表示所在格子有蚊子。
接下来一行,包含一个不超过 400 的正整数 k,表示发射炮弹的数量。
最后 k 行,每行包括一发炮弹的整数坐标 x 和 y(0 <= x <= M,0 <= y <= N),之间用一个空格间隔。
publicstaticvoidmain(String[] args){ Scanner scanner =newScanner(System.in); int m = scanner.nextInt(); int n = scanner.nextInt(); scanner.nextLine(); int[][] map =newint[m][n];// 记录每个位置上的文字的血量 for(int y =0; y != m;++y){ String input = scanner.nextLine(); for(int x =0; x != n;++x){ map[y][x]= input.charAt(x)=='0'?0:2; } } int k = scanner.nextInt(); for(int i =0; i != k;++i){ int y = scanner.nextInt(); int x = scanner.nextInt(); int count =0; if(map[y][x]>0){ map[y][x]=0; ++count; } if(x !=0&&--map[y][x -1]==0)++count; if(x +1!= n &&--map[y][x +1]==0)++count; if(y !=0&&--map[y -1][x]==0)++count; if(y +1!= m &&--map[y +1][x]==0)++count; System.out.println(count); } }
publicstaticvoidmain(String[] args){ Scanner scanner =newScanner(System.in); int n = scanner.nextInt(); int k = scanner.nextInt(); int s = scanner.nextInt(); Map<Integer,List<Integer>> input =newTreeMap<>(); for(int i =0; i != n;++i){ int key = scanner.nextInt(); int pat = scanner.nextInt(); // 因为参赛成绩小于 175 的不可能被接受,直接忽略 if(key >=175) input.computeIfAbsent(key, t ->newArrayList<>()).add(pat); } input.forEach((key, pats)-> pats.sort(Integer::compare)); AtomicInteger ans =newAtomicInteger(); input.forEach((key, pats)->{ int index =Collections.binarySearch(pats, s); if(index <0) index =-(index +1); ans.addAndGet(Math.min(pats.size()- index + k, pats.size())); }); System.out.println(ans); }
}
朋友圈
某学校有 N 个学生,形成 M 个俱乐部。每个俱乐部里的学生有着一定相似的兴趣爱好,形成一个朋友圈。一个学生可以同时属于若干个不同的俱乐部。根据“我的朋友的朋友也是我的朋友”这个推论可以得出,如果 A 和 B 是朋友,且 B 和 C 是朋友,则 A 和 C 也是朋友。请编写程序计算最大朋友圈中有多少人。
publicstaticvoidmain(String[] args)throwsIOException{ int n =read(); int m =read(); union =newint[n +1]; count =newint[n +1]; Arrays.fill(count,1); for(int i =1; i != union.length;++i) union[i]= i; for(int i =0; i != m;++i){ int c =read(); if(c ==0)continue; int key =read(); for(int k =1; k != c;++k){ merge(read(), key); } } System.out.println(Arrays.stream(count).max().getAsInt()); }
staticintread()throwsIOException{ int result =0; int input =System.in.read(); do{ result =(result <<1)+(result <<3)+(input ^48); input =System.in.read(); }while(Character.isDigit(input)); return result; }
publicstaticvoidmain(String[] args){ Scanner scanner =newScanner(System.in); int n = scanner.nextInt(); Node[] deque =newNode[n <<1]; int left = n, right = n; for(int i =0; i != n;++i){ String op = scanner.next(); if(op.charAt(0)=='G'){ if(right - left ==0)System.out.println("EMPTY QUEUE!"); elseSystem.out.println(deque[left++].message); }else{ Node node =newNode(scanner.next(), scanner.nextInt()); // 二分查找插入点 int index =-Arrays.binarySearch(deque, left, right, node)-1; // 如果插入点右侧元素(包括插入点)数量少就让右侧元素向右移动 // 否则让插入点左侧元素(不包括插入点)向左移动 if(right - index < index - left){ System.arraycopy(deque, index, deque, index +1, right - index); deque[index]= node; ++right; }else{ System.arraycopy(deque, left, deque, left -1, index - left); deque[index -1]= node; --left; } } } }
publicstaticvoidmain(String[] args)throwsIOException{ int n =read(); int[] array =newint[n]; int size =0; for(int i =0; i != n;++i){ int code =read(); if(size ==0){ array[size++]= code; continue; } int index =-Arrays.binarySearch(array,0, size, code)-1; if(index == size) array[size++]= code; else array[index]= code; } System.out.println(size); }
staticintread()throwsIOException{ int result =0; int input =System.in.read(); do{ result =(result <<1)+(result <<3)+(input ^48); input =System.in.read(); }while(Character.isDigit(input)); return result; }
}
拯救 007
在老电影“007之生死关头”(Live and Let Die)中有一个情节,007 被毒贩抓到一个鳄鱼池中心的小岛上,他用了一种极为大胆的方法逃脱 —— 直接踩着池子里一系列鳄鱼的大脑袋跳上岸去!(据说当年替身演员被最后一条鳄鱼咬住了脚,幸好穿的是特别加厚的靴子才逃过一劫。)
staticintread()throwsIOException{ int result =0; int input =System.in.read(); do{ result =(result <<1)+(result <<3)+(input ^48); input =System.in.read(); }while(Character.isDigit(input)); return result; }
}
红色警报
战争中保持各个城市间的连通性非常重要。本题要求你编写一个报警程序,当失去一个城市导致国家被分裂为多个无法连通的区域时,就发出红色警报。注意:若该国本来就不完全连通,是分裂的 k 个区域,而失去一个城市并不改变其他城市之间的连通性,则不要发出警报。
publicstaticvoidmain(String[] args)throwsIOException{ int n =read(), m =read(); union =newint[n]; map =newArrayList<>(n); delete =newboolean[n]; for(int i =0; i != n;++i) map.add(newTreeSet<>()); for(int i =0; i != m;++i){ int a =read(), b =read(); map.get(a).add(b); map.get(b).add(a); } int last =count(); int k =read(); for(int i =0; i != k;++i){ int code =read(); delete[code]=true; int next =count(); // 注意输出结尾标点符号不一样 if(next - last >1) System.out.printf("Red Alert: City %d is lost!\n", code); elseSystem.out.printf("City %d is lost.\n", code); last = next; } if(k == n) System.out.print("Game Over."); }
staticint[] union;
staticintcount(){ for(int i =0; i != union.length;++i) union[i]= i; for(int i =0; i < map.size(); i++){ if(delete[i])continue; int dist =find(i); for(int value : map.get(i)){ if(!delete[value]) union[value]= dist; } } int result =0; for(int i =0; i < union.length; i++){ if(find(i)== i)++result; } return result; }
staticintread()throwsIOException{ int result =0; int input =System.in.read(); do{ result =(result <<1)+(result <<3)+(input ^48); input =System.in.read(); }while(Character.isDigit(input)); return result; }
}
单调栈
N 人们排队等着参加音乐会。人们等得很无聊,于是他们转身去排队寻找熟悉的人。
如果两个人 A 和 B 并排站在一起,或者如果他们中间没有人比 A 或 B 高,那么他们可以看到对方。
publicstaticvoidmain(String[] args)throwsIOException{ int n =read(); long result =0; // 使用双向队列模拟栈 // Java 中不要使用 Stack 当作栈,Stack 是一个线程安全的类,基于 Vector 实现,效率很低,官方已经不再推荐使用该类 Deque<Node> stack =newLinkedList<>(); for(int i =0; i != n;++i){ int height =read(); // 规则 3 while(!stack.isEmpty()){ Node top = stack.getLast(); if(top.height < height){ // 本来这里是 +1,但是因为我们合并了相邻且等高的人,所以需要加 count result += top.count; stack.removeLast(); }elsebreak; } // 因为栈为空的时候没办法取元素,所以先特判一下,算是规则 1 的一部分 if(stack.isEmpty()) stack.add(newNode(height)); else{ // 规则 2 Node last = stack.getLast(); if(last.height == height){ result += last.count++; if(stack.size()!=1)++result; }else{ // 规则 1 的剩下一部分 stack.add(newNode(height)); ++result; } } } System.out.print(result); }
staticintread()throwsIOException{ int result =0; int input =System.in.read(); do{ result =(result <<1)+(result <<3)+(input ^48); input =System.in.read(); }while(Character.isDigit(input)); return result; }