4873. 简单计算
给定四个整数 x1,y1,x2,y2,请你计算 max(|x1−x2|,|y1−y2|)。
输入格式
第一行包含两个整数 x1,y1。
第二行包含两个整数 x2,y2。
输出格式
一个整数,表示 max(|x1−x2|,|y1−y2|) 的值。
数据范围
前 4 个测试点满足 −10≤x1,y1,x2,y2≤10。
所有测试点满足 −109≤x1,y1,x2,y2≤109。输入样例1:
0 0 4 5
输出样例1:
5
输入样例2:
3 4 6 1
输出样例2:
3
按照题意模拟即可。(注意不要将y1
定义成全局变量,因为某些头文件中可能用过y1
,会造成编译错误)。
时间复杂度为O(1)
#include
#include
#include
using namespace std;
int main(){
int x1,x2,y1,y2; //注意不要将y1,定义到全局,因为某些头文件中可能用过y1,可能会造成编译错误
cin>>x1>>y1>>x2>>y2;
int ans=max(abs(x1-x2),abs(y1-y2));
cout<<ans;
return 0;
}
4874. 约数
如果一个正整数的约数个数恰好为 3,则称该数为美丽数。
给定 n 个正整数 a1,a2,…,an,请你依次判断每个数是否是美丽数。
输入格式
第一行包含整数 n。
第二行包含 n 个整数 a1,a2,…,an。
输出格式
共 n 行,其中第 i 行输出对 ai 的判断,如果 ai 是美丽数,则输出
YES
,否则输出NO
。数据范围
前 6 个测试点满足 1≤n≤10。
所有测试点满足 1≤n≤105,1≤ai≤1012。输入样例:
3 4 5 6
输出样例:
YES NO NO
我的思路
比赛的时候试除法判定质数超时了,最后四个数据过不了,所以对试除法做了终极优化,但是今天我试了一下比赛时的试除法的代码竟然可以AC也不知道什么原因,估计比赛时评测的人太多了?所以下面只给出朴素版的判定质数代码。
(1)其实比赛时也没想到怎么优化,只是找规律,比如9是美丽数,它的三个约数是1,3,9;25也是美丽数,它的三个约数是1,5,25;49也是美丽数,它的三个约数是1,7,49。发现什么规律没有?规律就是:这些美丽数都是完全平方数,但是16是美丽数吗?显然不是,因为16的约数是1,2,4,8,16不是3个;36也不是美丽数,因为36的约数是1,2,3,4,6,9,12,18,36不是3个,所以我们又可以得到一个规律:美丽数一定是质数的完全平方。
(2)综上:我们得到美丽数就是是质数的完全平方数,按此条件依次每个数判断即可。
y总思路
思路来源:y总讲解视频
y总yyds
(1)一个结论:完全平方数的约数个数一定为奇数个,反之亦然。
(2)因为美丽数只存在3个约数,也就是1,其平方根和其本身,所以其平方根一定是质数。
(3)根据上述条件:美丽数是质数的完全平方,对每个数进行判断即可,判断质数可以利用质数筛先将1~106(因为a[i]
最大1012,其平方根最大106)所有质数先筛出来,然后查表判断是否是质数。
时间复杂度为O(n√n)
时间复杂度为O(n)
我的思路
#include
#include
#include
using namespace std;
typedef long long LL;
const int N=100010;
int n;
LL a[N]; //注意范围,开long long
//试除法判定x是否是质数
bool isPrime(int x){
if(x<2) return false;
for(int i=2;i<=x/i;i++){
if(x%i==0) return false;
}
return true;
}
//判断a是否是美丽数
bool check(LL a){ //注意开LL
LL g=sqrt(a); //注意开LL
if(g*g==a&&isPrime(g)) return true;
return false;
}
int main(){
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<n;i++){
bool flag=check(a[i]);
if(flag) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
y总思路
#include
#include
#include
using namespace std;
typedef long long LL;
const int N=1000010;
int n,cnt;
int primes[N]; //存储所有质数
bool st[N]; //存储每个数是否被筛掉
LL a[N]; //注意范围,需开long long
//线性筛法将1~10^6所有质数筛出来
void getPrime(int x){
st[0]=st[1]=true;
for(int i=2;i<=x;i++){
if(!st[i]) primes[cnt++]=i;
for(int j=0;primes[j]<=x/i;j++){
st[primes[j]*i]=true;
if(i%primes[j]==0) break;
}
}
}
//判断a是否是美丽数
bool check(LL a){ //注意LL
LL g=sqrt(a); //注意LL
if(g*g==a&&!st[g]) return true;
return false;
}
int main(){
cin>>n;
getPrime(1000000);
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<n;i++){
bool flag=check(a[i]);
if(flag) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
4875. 整数游戏
Alice 和 Bob 在玩一个游戏。
首先,给定一个长度为 n 的正整数数列 a1,a2,…,an。
随后,两人轮流展开行动,由 Alice 先手行动。
当轮到一人采取行动时,如果 a1=0,则该玩家输掉游戏,否则该玩家需要:
- 在 [2,n] 范围内选择一个整数 i。
- 将 a1 的值减少 1。
- 交换 a1 和 ai 的值。
假设双方都采取最优策略,请你判断谁将获胜。
输入格式
第一行包含整数 T,表示共有 T 组测试数据。
每组数据第一行包含整数 n。
第二行包含 n 个整数 a1,a2,…,an。
输出格式
每组数据输出一行结果,如果 Alice 获胜,则输出
Alice
,如果 Bob 获胜,则输出Bob
。数据范围
前 3 个测试点满足 1≤T≤10,2≤n≤3。
所有测试点满足 1≤T≤2×104,2≤n≤105,1≤ai≤109,一个测试点的所有的 n 相加之和不超过 2×105。输入样例:
3 2 1 1 2 2 1 3 5 4 4
输出样例:
Bob Alice Alice
思路来源:y总讲解视频
y总yyds
(1)所以可以寻找规律进行假设:如果第一个数是数组中最小的数则先手必输,否则先手必胜。
(2)根据上述假设我们可以知道
即需证明:如果先手操作完之后从先手必胜态可以转化成某一个先手必败态,即后手开始操作时,总是必败,说明此时先手必胜;同理,如果先手操作完之后从先手必败态只能转化成先手必胜态,即后手开始操作时,总是必胜,则此时先手必输。
(3)对于先手必胜态,由于第一个数不是最小的,我们可以将第一个数减1之后将最小的数换到第一个数,即可以转化成某一个先手必败态;对于先手必败态,由于第一个数已经是最小的了,我们将第一个数减1之后,该数还是最小的,我们无论拿谁来与它交换,都使得第一个数不是最小数,即只能转化为先手必胜态。
(4)说明我们假设正确:如果第一个数是数组中最小的数则先手必输,否则先手必胜。据此判断先手必胜/先手必败即可。
时间复杂度为O(n)
#include
#include
using namespace std;
const int N=100010;
int a[N];
int T,n;
int main(){
cin>>T;
while(T--){
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
int m=a[0]; //m存储a[]中最小的数
for(int i=0;i<n;i++) m=min(m,a[i]); //寻找a[]中最最小的数
//如果第一个数为最小数,则先手必败,否则先手必胜
if(m==a[0]) cout<<"Bob"<<endl;
else cout<<"Alice"<<endl;
}
return 0;
}