Codeforces Round #655 (Div. 2) / contest 1372


题目地址:https://codeforces.com/contest/1372



A Omkar and Completion

题意:签到题

思路

代码

#define DIN freopen("input.txt","r",stdin);
#define DOUT freopen("output.txt","w",stdout);
#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=(a);i<=(int)(b);i++)
#define REP_(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> P;
int read()
{
    int x=0,flag=1;
    char c=getchar();
    while((c>'9' || c<'0') && c!='-') c=getchar();
    if(c=='-') flag=0,c=getchar();
    while(c<='9' && c>='0') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
    return flag?x:-x;
}

int main()
{
    int T=read();
    while(T--)
    {
        int n=read();
        REP_(i,n,1) printf("1 ");
        puts("");
    }

    return 0;
}



B Omkar and Last Class of Math

题意:给出一个 n,要求两个正整数 a 和 b,使得 a+b=n 并且 LCM(a, b) 尽量小。多组数据。

思路:显然应该找出 n 的大于 1 的最小因子 k,然后把 n 分成 k 份,其中的一份是 a,k-1 份是 b。

代码

#define DIN freopen("input.txt","r",stdin);
#define DOUT freopen("output.txt","w",stdout);
#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=(a);i<=(int)(b);i++)
#define REP_(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> P;
int read()
{
    int x=0,flag=1;
    char c=getchar();
    while((c>'9' || c<'0') && c!='-') c=getchar();
    if(c=='-') flag=0,c=getchar();
    while(c<='9' && c>='0') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
    return flag?x:-x;
}

int main()
{
    int T=read();
    while(T--)
    {
        int n=read(),x=1;
        for(int i=2;i*i<=n;i++)
        if(n%i==0) {x=i; break;}
        if(x==1) printf("%d %d\n",x,n-x);
        else printf("%d %d\n",n/x,1ll*n*(x-1)/x);
    }

    return 0;
}



C Omkar and Baseball

题意:有一个操作:选出数组中的一段区间,然后把这段区间中的数全部打乱,使得没有任何数在原来的位置。现在给你一个 n 的排列 a,问你最少操作多少次,可以让 a 变成严格单增数列。

思路:如果本来就单调递增,操作次数为 0 次;然后我们忽略 a 的前后已经排好的(也就是说前面是 1 2 3... ,后面是 n n-1 n-2... 的这些都忽略),剩下的那一段中间的区间中,如果有值等于下标的元素,那么需要 2 次,如果没有那么需要 1 次。

代码

#define DIN freopen("input.txt","r",stdin);
#define DOUT freopen("output.txt","w",stdout);
#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=(a);i<=(int)(b);i++)
#define REP_(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> P;
int read()
{
    int x=0,flag=1;
    char c=getchar();
    while((c>'9' || c<'0') && c!='-') c=getchar();
    if(c=='-') flag=0,c=getchar();
    while(c<='9' && c>='0') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
    return flag?x:-x;
}

const int maxn=2e5+5;
int a[maxn],n;

bool check1()
{
    REP(i,1,n-1) if(a[i]>a[i+1]) return 0;
    return 1;
}

bool check2()
{
    int last=n,first=1;
    while(last>0 && a[last]==last) last--;
    while(first<=n && a[first]==first) first++;
    REP(i,first,last) if(a[i]==i) return 0;
    return 1;
}

int main()
{
    int T=read();
    while(T--)
    {
        n=read();
        REP(i,1,n) a[i]=read();
        if(check1()) puts("0");
        else if(check2()) puts("1");
        else puts("2");
    }

    return 0;
}



D Omkar and Circle

题意:有一个奇环,每个结点有一个权值。每次你可以选择一个结点,然后把它的权值替换为与它相邻两个结点权值之和,然后把与它相邻的两个结点删去。问最后剩下一个结点时,权值最大为多少?

思路:一开始想的完全是贪心,然后怎么也不对。

最优的策略一定是选择 (n+1)/2 个不相邻的元素(这里面有一对是相邻的),首先元素不相邻这是肯定的,因为合并的时候只能合并不相邻的两个元素,其次如果你选择的元素个数小于 (n+1)/2 也是有可能的(比如套娃式合并),但是这样显然没有选择 (n+1)/2 个更优。而选择 (n+1)/2 个就意味着,我们要选择所有奇数位,或者所有偶数位,所以做法就是把奇偶分开,然后合并,然后计算前缀和,然后求一段长度为 (n+1)/2 的和的最大值。

代码

#define DIN freopen("input.txt","r",stdin);
#define DOUT freopen("output.txt","w",stdout);
#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=(a);i<=(int)(b);i++)
#define REP_(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> P;
int read()
{
    int x=0,flag=1;
    char c=getchar();
    while((c>'9' || c<'0') && c!='-') c=getchar();
    if(c=='-') flag=0,c=getchar();
    while(c<='9' && c>='0') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
    return flag?x:-x;
}

const int maxn=2e5+5;
LL a[maxn],b[maxn];

int main()
{
    int n=read(),m=0;
    REP(i,1,n) a[i]=read();
    for(int i=1;i<=n;i+=2) b[++m]=a[i];
    for(int i=2;i<=n;i+=2) b[++m]=a[i];
    REP(i,n+1,n*2) b[i]=b[i-n];
    REP(i,1,n*2) b[i]+=b[i-1];
    LL ans=0;
    REP(i,(n+1)/2,n*2) ans=max(ans,b[i]-b[i-(n+1)/2]);
    cout<<ans;

    return 0;
}



E

题意

思路

代码




F

题意

思路

代码


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值