题目
- A.最近距离(签到题)
- B.这是一道特别简单的题目(简单数学题)
- C.M78星云的字符转换(基础题)
- D.M78星云的排队事故(前缀和板子题)
- F.不服气的洁洁学姐(gcd)
- E.来自M78星云的小测试(进制转换+回文)
- G.来自M78星云的减法运算(模拟题/彩蛋题)
A.最近距离(签到题)
题目
思路:
只需要判断AB直线是否垂直坐标轴且F点在AB线段之间即可,若不符合:代表A、B点之间的最短路径不止一条,最终结果就为A、B两点的横纵坐标差的绝对值之和;如果符合,则代表A、B点之间的最短路径只有一条,则A到B点是需要绕过F点,则在不符合的条件上加上绕路的距离2。
代码:
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int t;
scanf("%d",&t);
while(t--){
int Ax,Ay,Bx,By,Fx,Fy;
//读入A、B、F点坐标
scanf("%d %d",&Ax,&Ay);
scanf("%d %d",&Bx,&By);
scanf("%d %d",&Fx,&Fy);
int ans = abs(Bx - Ax) + abs(By - Ay);//计算A、B点的横纵坐标差的绝对值之和
if(Ax == Bx && Bx == Fx && Fy > min(Ay,By) && Fy < max(Ay,By)) ans += 2;
//判断是否AB线段垂直与x轴且F点在AB线段之间
if(Ay == By && By == Fy && Fx > min(Ax,Bx) && Fx < max(Ax,Bx)) ans += 2;
//判断是否AB线段垂直与y轴且F点在AB线段之间
printf("%d\n",ans);
}
return 0;
}
B.这是一道特别简单的题目(简单数学题)
题目:
思路:
让你判断一个数是否有除1以外的奇数因数,只需要将数进行完全的因数分解(分解为全为质数相乘的形式),
发现,只有当因数全为2(换句话说就是这个数是2n)时,没有除1以外的奇数因子。
代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
long long n;
cin >> n;
//如果n为整数,就不断/2知道其为奇数
while(n % 2 == 0 ){
n /= 2;
}
//只需要判断这个奇数是否为1,为1证明这个数完全分解的因子全为2,反之亦然
if(n != 1) cout<<"YES";
else cout<<"NO";
return 0;
}
C.M78星云的字符转换(基础题)
题目:
思路:
通过ASCLL码转换,将小写字符转化为大写字母,如果忘了大小写字母相差多少位的,可以输出一下小写字母减大写字母来看一下。
代码:
#include<stdio.h>
#include<string.h>
int main()
{
char str[1010];
//字符串读入方式
scanf("%s",str);
//strlen函数求字符串长度
for(int i = 0 ; i < strlen(str) ; i ++){
//根据ASCLL码小写字母比大写字母大32来转换大小写字母
if(str[i] >= 'a' && str[i] <= 'z') str[i] -= 32;
}
printf("%s",str);
return 0;
}
D.M78星云的排队事故(前缀和板子题)
题目:
思路:
基础前缀和知识运用,先进行排序,再求区间 [l,r] 的和即求 [1,r] - [1,l - 1] 的值即可。
代码:
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e3 + 10;
int arr[N];
int q[N];//前缀和数组 ,q[i]代表[1,i]区间中所有值的和
int n,l,r;
int main()
{
scanf("%d",&n);
for(int i = 1 ; i <= n ; i ++){
scanf("%d",&arr[i]);
}
sort(arr + 1 , arr + 1 + n);//sort排序函数,也可以自己写冒泡代替
//求前缀和数组
for(int i = 1 ; i <= n ; i ++) q[i] = q[i - 1] + arr[i];
scanf("%d %d",&l,&r);
printf("%d",q[r] - q[l - 1]);
return 0;
}
F.不服气的洁洁学姐(gcd)
题目:
思路:
不限次数对数组任意区间减去相同的值,最终使数组所有值相同,假定减去的值为K,对数组任意 arri 可假设其减少了n次K值后变为定值s,即 arri - nK = s, 数组中每个值在变化前后均满足此式,求K的最大值,即求数组中所有减少量nK的最大公约数(gcd)。对于每一个数减少的量一定使K的倍数或为0,于是相邻两个数做差 |arra - arrb |= |(aK + s) - (bK + s) |= |(a-b)K|,所以只需要对所有相邻的两个数的差值的绝对值(不为0,为0没意思)求最大公约数即可。
代码:
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e6 + 10;
int arr[N],q[N];
int n;
int gcd(int a , int b)
{
if(b == 0) return a;
return gcd(b,a%b);
}
int main()
{
scanf("%d",&n);
for(int i = 0 ; i < n ; i ++) scanf("%d",&arr[i]);
int k = 0;
//相邻两位做差,得到K的倍数
for(int i = 0 ; i + 1 < n ; i ++)
if(arr[i + 1] - arr[i])//将所有不为0的差值的绝对值存入q数组
q[k++] = abs(arr[i + 1] - arr[i]);
int ans = q[0];
//对k个K的倍数求最大公约数,得到结果
for(int i = 1 ; i < k ; i ++) ans = gcd(ans , q[i]);
//若ans == 0 ,代表arr数组中所有值相等,K最大值趋于无穷
if(ans == 0) printf("-1");
else printf("%d",ans);
return 0;
}
E.来自M78星云的小测试(进制转换+回文)
题目:
思路:
将数字转化为m进制后用字符串形式存储,然后用双指针一头一尾向中间跑,不断进行比较判断是否为回文即可。
代码:
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e4 + 10;
int n , m;
char q[20] = "0123456789ABCDEF";
bool check(int a)
{
char s[100];//存储a转换为m进制后的字符串
int k = 0;//记录转换为字符串后的位数
a = a * a;
//进行进制转换
while(a){
s[k ++] = q[a % m];
a /= m;
}
//从头尾向中间比较是否字符相同,若存在不同则不为回文
int i = 0, j = k - 1;
while(i < j){
if(s[i] == s[j]) i++,j--;
else return false;//不满足回文返回false
}
return true;
}
int main()
{
scanf("%d %d",&n,&m);
int ans = 0;
for(int i = 1 ; i <= n ; i ++){
if(check(i)) ans ++;//记录满足回文的数量
}
printf("%d",ans);
}
G.来自M78星云的减法运算(模拟题/彩蛋题)
题目:
思路:
python解法(最简单的解法):
由于python的整数没有范围限制,之间定义两个数做差即可。
代码:
a = int(input().strip())
b = int(input().strip())
print(a-b)
c/c++解法(大模拟):
用数组模拟计算过程。
代码:
#include<bits/stdc++.h>
using namespace std;
//判断A是否大于B
bool check(string str1 , string str2)
{
int len1 = str1.length(),len2 = str2.length();
if(len1 != len2) return len1 > len2;
for(int i = len1 - 1 ;i >= 0 ; i --)
if(str1[i] != str2[i]) return str1[i] > str2[i];
return true;
}
int main()
{
string str1,str2;
cin>>str1>>str2;
int ans[1000];
bool s = true;
if(!check(str1,str2)){
//如果A<B,交换A,B,并用s记录结果为负
swap(str1,str2);
s = false;
}
int i = str1.length() - 1, j = str2.length() - 1;
int k = 0,cn = 0; //k代表是否借位
//A - B的模拟计算过程
while(i >= 0 && j >= 0){
if(str1[i] + k < str2[j]){
ans[cn ++] = str1[i] - str2[j] + 10 + k ;
k = -1;
}else{
ans[cn++] = str1[i] - str2[j] + k ;
k = 0;
}
i--,j--;
}
//A的位数多余B,要将A多余位数加上
while(i >= 0){
if(str1[i] - '0' + k >= 0){
ans[cn++] = str1[i] - '0' + k;
k = 0;
}else{
ans[cn++] = str1[i] - '0' + k + 10;
k = -1;
}
i--;
}
//同理B的位数多余A,要将B多余位数加上
while(j >= 0){
if(str2[j] - '0' + k >= 0){
ans[cn++] = str2[j] - '0' + k;
k = 0;
}else{
ans[cn++] = str2[j] - '0' + k + 10;
k = -1;
}
j--;
}
if(!s) cout<<"-";
while(!ans[cn - 1] && cn > 1) cn--;
for(int i = cn - 1 ; i >= 0 ; i --) cout<<ans[i];
}