题目大意:
给你一个
n
n
n,要你构造一个长度为
n
n
n的数组使得
a
i
+
a
j
!
=
a
z
ai+aj!=az
ai+aj!=az。
思路:
直接构造
n
n
n个
x
x
x即可,
x
x
x可以取任意数,我这里
x
x
x取的
2
2
2。
代码:
#include<iostream>
using namespace std;
typedef long long int ll;
const int maxn = 2e5 + 10;
void solved(){
int n;cin>>n;
for(int i = 1; i <= n; i++)cout<<"2"<<" ";
cout<<endl;
}
int main(){
int t;
while(cin>>t){
while(t--)solved();
}
return 0;
}
题目大意:
给你一个
n
n
n,要你输出
a
,
b
a,b
a,b,使得
a
+
b
=
n
a+b=n
a+b=n并且
m
i
n
(
l
c
m
(
a
,
b
)
)
min(lcm(a,b))
min(lcm(a,b))。
思路:
如果
n
n
n为偶数,答案显然是
n
/
2
,
n
/
2
n/2,n/2
n/2,n/2。
如果
n
n
n是奇数,我们不妨拆开看看
1
+
(
n
−
1
)
,
2
+
(
n
−
2
)
,
3
+
(
n
−
3
)
,
.
.
.
1+(n-1),2+(n-2),3+(n-3),...
1+(n−1),2+(n−2),3+(n−3),...,我们知道
l
c
m
(
a
,
b
)
=
a
∗
b
/
g
c
d
(
a
,
b
)
lcm(a,b)=a*b/gcd(a,b)
lcm(a,b)=a∗b/gcd(a,b)。假设
g
c
d
(
a
,
b
)
=
1
,
a
∗
b
是
递
增
的
gcd(a,b)=1,a*b是递增的
gcd(a,b)=1,a∗b是递增的,但是当
g
c
d
(
a
,
b
)
>
1
gcd(a,b)>1
gcd(a,b)>1,那么这个数就会缩小
m
i
n
(
a
,
b
)
min(a,b)
min(a,b)倍,所以我们只需要找到最大的
g
c
d
(
a
,
b
)
gcd(a,b)
gcd(a,b),并且这个
g
c
d
(
a
,
b
)
gcd(a,b)
gcd(a,b)是
n
n
n的因子,所以我们枚举
n
n
n的因子就好了,我们只需要找到一个最小的因子,然后
n
/
这
个
因
子
n/这个因子
n/这个因子,就是最大因子了,也就是最大的
g
c
d
(
a
,
b
)
gcd(a,b)
gcd(a,b)。素数特判。
时间复杂度
O
(
s
q
r
t
(
n
)
)
O(sqrt(n))
O(sqrt(n))。
代码:
#include<iostream>
using namespace std;
typedef long long int ll;
bool is_prime(ll x){
for(int i = 2; i * i <= x; i++){
if(x % i == 0)return false;
}return true;
}
void solved(){
ll n;cin>>n;
if(n & 1){
if(is_prime(n)){cout<<"1 "<<n - 1<<endl;return ;}
ll p = 0;
for(ll i = 2; i * i <= n; i++){
if(n % i == 0){p = i;break;}
}
cout<<n/p<<" "<<n-n/p<<endl;
}else{
cout<<(n/2)<<" "<<(n/2)<<endl;
}
}
int main(){
int t;cin>>t;
while(t--)solved();
return 0;
}
题目大意:
给你一个排列,问你将它变得有序最少要几次特殊变换,特殊变化:任取一个区间,只要该数字不在原来的位置上就随便你换。
思路:
通过观察可以发现,答案不会超过
2
2
2。
当排列是有序的,输出
0
0
0。
从左到右,找到第一个
l
!
=
a
l
l!=al
l!=al的位置,然后从右到左边找到第一个
r
!
=
a
r
r!=ar
r!=ar的位置,然后在这个区间找,如果存在一个
a
i
=
=
i
ai==i
ai==i,说明至少要两次变换才行,输出
2
2
2.
其他输出
1
1
1。
代码:
#include<iostream>
#include<stdlib.h>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long int ll;
const int maxn = 2e5 + 10;
void solved(){
int n;cin>>n;
vector<int>ve;
ve.push_back(0);
for(int i = 1; i <= n; i++){
int x;cin>>x;
ve.push_back(x);
}
vector<int>b = ve;
sort(b.begin(),b.end());
if(ve == b){
cout<<"0"<<endl;
return ;
}
int l = 1,r = n;
while(ve[l] == l && l <= n){l++;}
while(ve[r] == r && l >= 1){r--;}
for(int i = l; i <= r; i++){
if(ve[i] == i){
cout<<"2"<<endl;
return ;
}
}
cout<<"1"<<endl;
}
int main(){
int t;
while(cin>>t){
while(t--)solved();
}
return 0;
}
题目大意:
给你
n
n
n个数,然后
a
i
与
a
i
+
1
,
和
a
i
−
1
ai与ai+1,和ai-1
ai与ai+1,和ai−1相邻,现在你可以选择一个数,然后用它两个相邻的和替换这个数,然后删除两个相邻的数,问最后的值最大是多少。
思路:
这题没写出来,参考的这篇博客:
https://blog.csdn.net/Satur9/article/details/107301466?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-1.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-1.nonecase
大概思路是:因为只能选不相邻的数,所以求出不相邻的数的前缀和和后缀和,然后错位求最大值。错位是防止某个数被多选。
代码:
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
const int maxn = 2e5 + 10;
typedef long long int ll;
ll a[maxn],b[maxn],c[maxn];
void solved(){
int n;cin>>n;
for(int i = 1;i <= n; i++){cin>>a[i];}
for(int i = 1; i <= n; i++){
if(i <= 2){b[i] = a[i];continue;}
b[i] = a[i] + b[i - 2];
}
if(n == 1){
cout<<a[1]<<endl;return ;
}
if(n == 2){
cout<<max(a[1],a[2])<<endl;return ;
}
for(int i = n; i >= 1; i--){
if(i + 2 > n){c[i] = a[i];}
c[i] = c[i + 2] + a[i];
}
ll res = 0;
// for(int i = 1; i <= n; i++)cout<<b[i]<<" ";cout<<endl;
// for(int i = 1; i <= n; i++)cout<<c[i]<<" ";cout<<endl;
for(int i = 1; i <= n; i++){
res = max(res,b[i] + c[i + 1]);
}
cout<<res<<endl;
}
int main(){
solved();
return 0;
}