前言
本人菜鸡一枚,如有错误,评论区指正,本文主要为算法新手在比赛中骗分提供一些思路,这皆是我的一家之言,大伙看个乐就行了。
一、A:阶乘求和
令
S = 1! + 2! + 3! + ... + 202320232023!,求
S 的末尾 9 位数字。
提示:答案首位不为 0。
public class Main{
public static void main(String[] args) {
long sum=0;
long t=1000000000;
long temp=1;
for(int i=1;i<=100;i++){
temp=(temp*i)%t;
sum=(sum+temp)%t;
}
System.out.println(sum);
}
}
总结
这题不能用暴力解决,毕竟10的11次方了。这题只要求观察出1!到39!之和后面的末尾9位数没有变过即可解决,如果有接触过这种类型题,可快速完成
二、B: 幸运数字
哈沙德数是指在某个固定的进位制当中,可以被各位数字之和整除的正整
数。例如 126 是十进制下的一个哈沙德数,因为 (126)10 mod (1+2+6) = 0;126
也是八进制下的哈沙德数,因为 (126)10 = (176)8,(126)10 mod (1 + 7 + 6) = 0;
同时 126 也是 16 进制下的哈沙德数,因为 (126)10 = (7
e)16,(126)10 mod (7 +
e) = 0。小蓝认为,如果一个整数在二进制、八进制、十进制、十六进制下均为
哈沙德数,那么这个数字就是幸运数字,第 1 至第 10 个幸运数字的十进制表示
为:1 , 2 , 4 , 6 , 8 , 40 , 48 , 72 , 120 , 126 . . . 。现在他想知道第 2023 个幸运数
字是多少?你只需要告诉小蓝这个整数的十进制表示即可。
public class Main{
public static void main(String[] args) {
int count=0;
while(true){
for(long i=1;;i++){
if(Is(i,2)&&Is(i,8)&&Is(i,10)&&Is(i,16)){
count++;
if(count==2023){
System.out.println(i);
return;
}
}
}
}
}
static boolean Is(long num,int n){
long t=num;
int sum=0;
while(t!=0){
sum=(int)(sum+(t%n));
t/=n;
}
return num%sum==0;
}
}
总结
答案:215040
简单进制转换。long换成int也是可以的,不会爆
三、C: 数组分割
小蓝有一个长度为
N 的数组
A = [
A0,
A1, . . . ,
A
N−1]。现在小蓝想要从
A 对 应的数组下标所构成的集合
I = {0, 1, 2, . . . ,
N − 1} 中找出一个子集
R1,那么
R1 在
I 中的补集为
R2。记
S 1 = ∑
r∈
R1
A
r,
S 2 = ∑
r∈
R2
A
r,我们要求
S 1 和
S 2 均为 偶数,请问在这种情况下共有多少种不的
R1。当
R1 或
R2 为空集时我们将
S 1 或
S 2 视为 0。 该处使用的url网络请求的数据。
【输入格式】
第一行一个整数
T,表示有
T 组数据。
接下来输入
T 组数据,每组数据包含两行:第一行一个整数
N,表示数组
A 的长度;第二行输入
N 个整数从左至右依次为
A0,
A1, . . . ,
A
N−1,相邻元素之
间用空格分隔。
【输出格式】
对于每组数据,输出一行,包含一个整数表示答案,答案可能会很大,你
需要将答案对 1000000007 进行取模后输出
【样例输入】
2
2
6 6
2
1 6
【样例输出】
4
0
对于第一组数据,答案为 4。(注意:大括号内的数字表示元素在数组中的
下标。)
R1 = {0},
R2 = {1};此时
S 1 =
A0 = 6 为偶数,
S 2 =
A1 = 6 为偶数。
R1 = {1},
R2 = {0};此时
S 1 =
A1 = 6 为偶数,
S 2 =
A0 = 6 为偶数。
R1 = {0, 1},
R2 = {};此时
S 1 =
A0 +
A1 = 12 为偶数,
S 2 = 0 为偶数。
R1 = {},
R2 = {0, 1};此时
S 1 = 0 为偶数,
S 2 =
A0 +
A1 = 12 为偶数。
对于第二组数据,无论怎么选择,都不满足条件,所以答案为 0。
【评测用例规模与约定】
对于 20% 的评测用例,1 ≤
N ≤ 10。
对于 40% 的评测用例,1 ≤
N ≤ 100。
对于 100% 的评测用例,1 ≤
T ≤ 10, 1 ≤
N ≤ 1000 , 0 ≤
A
i ≤ 1e9。
import java.util.Scanner;
public class Main{
static int T;
static long ans=0;
static int[] arr;
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
T=in.nextInt();
while (T!=0){
int n=in.nextInt();
arr=new int[n+1];
long sum=0;
for (int i = 1; i <=n; i++) {
arr[i]=in.nextInt();
sum+=arr[i];
}
if (sum%2==0){
ans++;
}
for (int i=1;i<=n;i++){
bfs(i+1,sum,arr[i]);
}
System.out.println(ans);
ans=0;
T--;
}
}
static void bfs(int next,long sum,long sum_temp){
if(sum_temp%2==0&&(sum-sum_temp)%2==0){
ans++;
ans=ans%1000000007;
}
for (int i=next;i<arr.length;i++){
bfs(i+1,sum,sum_temp+arr[i]);
}
}
}
总结
本人这题没有审题已寄,我以为是计算全部然后输出(样例的4,0是分页的),这题ans过大的话可能要用BigInteger处理。这题只需考虑{}和{全部}的关系,应该是能骗些分的
四、 D: 矩形总面积
平面上有个两个矩形
R1 和
R2,它们各边都与坐标轴平行。设 (
x1,
y1) 和
(
x2,
y2) 依次是
R1 的左下角和右上角坐标,(
x3,
y3) 和 (
x4,
y4) 依次是
R2 的左下
角和右上角坐标,请你计算
R1 和
R2 的总面积是多少?
注意:如果
R1 和
R2 有重叠区域,重叠区域的面积只计算一次。
【输入格式】
输入只有一行,包含 8 个整数,依次是:
x1,
y1,
x2,
y2,
x3,
y3,
x4 和
y4。
【输出格式】
一个整数,代表答案。
【样例输入】
2 1 7 4 5 3 8 6
【样例输出】
22
【评测用例规模与约定】
对于 20% 的数据,
R1 和
R2 没有重叠区域。
对于 20% 的数据,其中一个矩形完全在另一个矩形内部。
对于 50% 的数据,所有坐标的取值范围是 [0, 103 ]。
对于 100% 的数据,所有坐标的取值范围是 [0, 105 ]。
import java.util.HashSet;
import java.util.Scanner;
public class Main{
static HashSet<String> hs=new HashSet<>();
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
int x1,y1,x2,y2,x3,y3,x4,y4;
x1=in.nextInt();
y1=in.nextInt();
x2=in.nextInt();
y2=in.nextInt();
x3=in.nextInt();
y3=in.nextInt();
x4=in.nextInt();
y4=in.nextInt();
for (int i=x1;i<x2;i++){
for(int j=y1;j<y2;j++){
String str=""+i+"-"+j;
hs.add(str);
}
}
for (int i=x3;i<x4;i++){
for(int j=y3;j<y4;j++){
String str=""+i+"-"+j;
hs.add(str);
}
}
System.out.println(hs.size());
}
}
总结
模拟题,普通判断的话会有很多种情况,有时间的话可以思考一下,我大概估计有10+种,面积大应该会超时,骗分吧
五、E: 蜗牛
这天,一只蜗牛来到了二维坐标系的原点。
在
x 轴上长有
n 根竹竿。它们平行于
y 轴,底部纵坐标为 0,横坐标分别
为
x1,
x2, ...,
x
n。竹竿的高度均为无限高,宽度可忽略。蜗牛想要从原点走到第
n 个竹竿的底部也就是坐标 (
x
n, 0)。它只能在
x 轴上或者竹竿上爬行,在
x 轴
上爬行速度为 1 单位每秒;由于受到引力影响,蜗牛在竹竿上向上和向下爬行
的速度分别为 0.7 单位每秒和 1.3 单位每秒。
为了快速到达目的地,它施展了魔法,在第
i 和
i + 1 根竹竿之间建立了传
送门(0 <
i <
n),如果蜗牛位于第
i 根竹竿的高度为
a
i 的位置 (
x
i ,
a
i),就可以
瞬间到达第
i + 1 根竹竿的高度为
b
i+1 的位置 (
x
i+1,
b
i+1),请计算蜗牛最少需要
多少秒才能到达目的地。
【输入格式】
输入共 1 +
n 行,第一行为一个正整数
n;
第二行为
n 个正整数
x1,
x2, . . . ,
x
n;
后面
n − 1 行,每行两个正整数
a
i ,
b
i+1。
【输出格式】
输出共一行,一个浮点数表示答案(四舍五入保留两位小数)。
【样例输入】
3
1 10 11
1 1
2 1
【样例输出】
4.20
【样例说明】
蜗牛路线:
(0, 0) → (1, 0) → (1, 1) → (10, 1) → (10, 0) → (11, 0),花费时间为 1 + 0 1
.7 +
0 + 1 1
.3 + 1 ≈ 4.20
【评测用例规模与约定】
对于 20% 的数据,保证
n ≤ 15;
对于 100% 的数据,保证
n ≤ 105,
a
i ,
b
i ≤ 104,
x
i ≤ 109。
import java.util.HashSet;
import java.util.Iterator;
import java.util.Scanner;
public class Main{
static HashSet<String> hs=new HashSet<>();
static long[] arr;
static int[][] ab;
static int n;
static long x;
static int y;
static double t;
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
n=in.nextInt();
arr=new long[n];
for(int i=0;i<n;i++){
arr[i]=in.nextLong();
}
ab=new int[n-1][2];
for(int i=0;i<n-1;i++){
ab[i][0]=in.nextInt();
ab[i][1]=in.nextInt();
}
double min=Integer.MAX_VALUE;
dfs("",0);
Iterator<String> iterator = hs.iterator();
while (iterator.hasNext()) {
char[] next = iterator.next().toCharArray();
t=arr[0];
x=arr[0];
y=0;
get(next,0);
t=t+(y-0)*(10*1.0/13);
min=Math.min(t,min);
}
min+=0.005;
System.out.println(String.format("%.2f",min));
}
static void get(char[] chars,int index){
if(x==arr[n-1]){
return ;
}
if (chars[index]=='0'){
t=t+y*(10*1.0/13);
t=t+arr[index+1]-arr[index];
x=arr[index+1];
y=0;
}else{
if (y>ab[index][0]){
t=t+(y-ab[index][0])*(10*1.0/13);
}else{
t=t+(ab[index][0]-y)*(10*1.0/7);
}
x=arr[index+1];
y=ab[index][1];
}
index++;
get(chars,index);
}
static void dfs(String str,int count){
if(count==n-1){
hs.add(str);
return;
}
char a='0',b='1';
count=count+1;
dfs(str+a,count);
dfs(str+b,count);
}
}
总结
只能过30%左右的数据,没办法就只能暴力,喜欢拼运气可以直接随机。这里我不知道是自愿传送还是碰到那个点就会传送
六、F: 合并区域
小蓝在玩一款种地游戏。现在他被分配给了两块大小均为
N ×
N 的正方形
区域。这两块区域都按照
N ×
N 的规格进行了均等划分,划分成了若干块面积
相同的小区域,其中每块小区域要么是岩石,要么就是土壤,在垂直或者水平
方向上相邻的土壤可以组成一块土地。现在小蓝想要对这两块区域沿着边缘进
行合并,他想知道合并以后可以得到的最大的一块土地的面积是多少(土地的
面积就是土地中土壤小区域的块数)?
在进行合并时,小区域之间必须对齐。可以在两块方形区域的任何一条边
上进行合并,可以对两块方形区域进行 90 度、180 度、270 度、360 度的旋转,
但不可以进行上下或左右翻转,并且两块方形区域不可以发生重叠。
【输入格式】
第一行一个整数
N 表示区域大小。
接下来
N 行表示第一块区域,每行
N 个值为 0 或 1 的整数,相邻的整数
之间用空格进行分隔。值为 0 表示这块小区域是岩石,值为 1 表示这块小区域
是土壤。
再接下来
N 行表示第二块区域,每行
N 个值为 0 或 1 的整数,相邻的整
数之间用空格进行分隔。值为 0 表示这块小区域是岩石,值为 1 表示这块小区
域是土壤。
【输出格式】
一个整数表示将两块区域合并之后可以产生的最大的土地面积。
【样例输入】
4
0 1 1 0
1 0 1 1
1 0 1 0
1 1 1 0
0 0 1 0
0 1 1 0
1 0 0 0
1 1 1 1
【样例输出】
15
对于 30% 的数据,1 ≤
N ≤ 5。
对于 60% 的数据,1 ≤
N ≤ 15。
对于 100% 的数据,1 ≤
N ≤ 50。
import java.util.Scanner;
public class Main{
static int[][] arr1;
static int[][] arr2;
static int N;
public static void main(String[] args){
Scanner in=new Scanner(System.in);
N=in.nextInt();
arr1=new int[N][N];
arr2=new int[N][N];
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
arr1[i][j]=in.nextInt();
}
}
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
arr2[i][j]=in.nextInt();
}
}
int max=0;
int max1=0;
int max2=0;
for(int i=0;i<N;i++){
if(arr1[i][N-1]==1){
max1=Math.max(max1,get(i,N-1));
}
if(arr1[N-1][i]==1){
max1=Math.max(max1,get(N-1,i));
}
if(arr1[i][0]==1){
max1=Math.max(max1,get(i,0));
}
if(arr1[0][i]==1){
max1=Math.max(max1,get(0,i));
}
}
max+=max1;
for(int i=0;i<N;i++){
if(arr2[i][N-1]==1){
max2=Math.max(max2,get1(i,N-1));
}
if(arr2[N-1][i]==1){
max2=Math.max(max2,get1(N-1,i));
}
if(arr2[i][0]==1){
max2=Math.max(max2,get1(i,0));
}
if(arr2[0][i]==1){
max2=Math.max(max2,get1(0,i));
}
}
max+=max2;
System.out.println(max);
}
static int get(int x,int y){
int[][] arr=new int[N][N];
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
arr[i][j]=arr1[i][j];
}
}
arr1[x][y]=2;
if(x-1>=0&&arr1[x-1][y]==1){
bfs(x-1,y);
}
if(x+1<N&&arr1[x+1][y]==1){
bfs(x+1,y);
}
if(y-1>=0&&arr1[x][y-1]==1){
bfs(x,y-1);
}
if(y+1<N&&arr1[x][y+1]==1){
bfs(x,y+1);
}
int count=0;
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
if(arr1[i][j]==2){
count++;
}
}
}
arr1=arr;
return count;
}
static void bfs(int x,int y){
arr1[x][y]=2;
if(x-1>=0&&arr1[x-1][y]==1&&arr1[x-1][y]!=2){
bfs(x-1,y);
}
if(x+1<N&&arr1[x+1][y]==1&&arr1[x+1][y]!=2){
bfs(x+1,y);
}
if(y-1>=0&&arr1[x][y-1]==1&&arr1[x][y-1]!=2){
bfs(x,y-1);
}
if(y+1<N&&arr1[x][y+1]==1&&arr1[x][y+1]!=2){
bfs(x,y+1);
}
}
static int get1(int x,int y){
int[][] arr=new int[N][N];
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
arr[i][j]=arr2[i][j];
}
}
arr2[x][y]=2;
if(x-1>=0&&arr2[x-1][y]==1){
bfs1(x-1,y);
}
if(x+1<N&&arr2[x+1][y]==1){
bfs1(x+1,y);
}
if(y-1>=0&&arr2[x][y-1]==1){
bfs1(x,y-1);
}
if(y+1<N&&arr2[x][y+1]==1){
bfs1(x,y+1);
}
int count=0;
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
if(arr2[i][j]==2){
count++;
}
}
}
arr2=arr;
return count;
}
static void bfs1(int x,int y){
arr2[x][y]=2;
if(x-1>=0&&arr2[x-1][y]==1&&arr2[x-1][y]!=2){
bfs1(x-1,y);
}
if(x+1<N&&arr2[x+1][y]==1&&arr2[x+1][y]!=2){
bfs1(x+1,y);
}
if(y-1>=0&&arr2[x][y-1]==1&&arr2[x][y-1]!=2){
bfs1(x,y-1);
}
if(y+1<N&&arr2[x][y+1]==1&&arr2[x][y+1]!=2){
bfs1(x,y+1);
}
}
}
总结
bfs暴搜,选择最大值即可,也是考完才想起来直接报搜,大佬们看个乐就行了,明年蓝桥杯再见
吐槽
总体难度比往年差不多,就是简单题不再是白送分了。第一次参加蓝桥杯也很紧张。点名批评一下广东某水利学院的设备和监考老师的态度,手机响了不管?害我开局少考20+分钟,紧张体验感拉满