Codeforces Round #655 (Div. 2)(ABCD题解)

在这里插入图片描述
在这里插入图片描述
题目大意:
给你一个 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+(n1),2+(n2),3+(n3),...,我们知道 l c m ( a , b ) = a ∗ b / g c d ( a , b ) lcm(a,b)=a*b/gcd(a,b) lcm(a,b)=ab/gcd(a,b)。假设 g c d ( a , b ) = 1 , a ∗ b 是 递 增 的 gcd(a,b)=1,a*b是递增的 gcd(a,b)=1ab,但是当 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 aiai+1,ai1相邻,现在你可以选择一个数,然后用它两个相邻的和替换这个数,然后删除两个相邻的数,问最后的值最大是多少。
思路:
这题没写出来,参考的这篇博客:

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值