Codeforces Round 884 (Div. 1 + Div. 2) 题解A~D

发布时间 2023-07-13 11:48:13作者: 逐夜之光

我想想啊,这一场我才从发烧中爬起来打,勉勉强强做了一题,然后后面的全是构造,最后无奈下班。

脑袋有些晕,复杂一点的代码都不想写,实在是太痛苦了。

这一场掉74分。可能确实是不太行了,越打越菜。

A题

很简单一道题,样例里也给了解法,只要有a+b个,就可以保证后手赢。

B题

是构造,打表了,当时觉得万能解是可以质数在两边,非质数放中间,1在最中间,按从小到大左右发布,但是脑子烧坏了,写不出来,赛后补的。

题解的意思大概是,n<3时可单独处理,n>=3时,只要首个元素是2,末尾元素是3,中间元素是1就都是最优!

这个最优性证明是这样:

如何一个素性队列必定包含1,1放在最中间,即(n+1)/2的位置,因此如果n+1是素数,那么数组素性最大值应该是为(n+1)/2的平方,否则就是该基础减1即可。

所以代码大概长这个样就行:

void solve()
{
    int n;
    cin>>n;
    if(n<3)
    {
        for(int i=1;i<=n;i++) cout<<i<<" ";
        cout<<"\n";
        return;
    }
    a[n]=3,a[(n+1)/2]=1,a[1]=2;
    int x=n;
    for(int i=1;i<=n;i++)
        if(a[i]==0) a[i]=x--;
    for(int i=1;i<=n;i++) cout<<a[i]<<" ",a[i]=0;
    cout<<endl;
}

很简单的问题,别想复杂了。

 

C题

这里首先要确定一点,每次融合对队列的影响是这样的,如果是在中间发生:消失一个,两个合一个,总量-2;在边缘发生:总量-1;

那么无论怎样,边缘处理可以直接损失掉小于0的所有结果,除非所有元素均小于0,否则我们得到的结果一定要大于0.

之后考虑两个大于0的数合并,首先,距离为奇数的两个元素肯定合并不了,也就是说,奇数合奇数的,偶数合偶数的,那我们就把这个序列分割开了.

ok,现在只要找两个序列里的最大值,再比较即可.贪心来说,最优策略肯定是负数不要正数全拿,记得开longlong,这个题也就这样了.

我的代码是这样的:

void solve()
{
    int n;
    scanf("%d",&n);
    ll ans1=-1e9,ans2=-1e9;
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        ans1=max(ans1,a[i]);
        ans2=max(ans2,a[i]);
    }
    if(ans1<0)
    {
        cout<<ans1<<endl;
        return;
    }
    ans1=ans2=0;
    for(int i=1;i<=n;i++)
    {
        if(i%2==1)
        {
            dp[i]=max(0ll,ans1)+a[i];
            ans1=max(dp[i],ans1);
        }
        else
        {
            dp[i]=max(0ll,ans2)+a[i];
            ans2=max(dp[i],ans2);
        }
        //cout<<dp[i]<<" ";
    }//cout<<endl;
    cout<<max(ans1,ans2)<<endl;
}

 

D题

这一题我一看就知道应该与n的所有因数有关,其实还可以推到质因数.那么只要找到26以内的最小的非n的因数的质数k即可.

正确性是可以确定的,因为26以内前8个质数的积就已经大于n的范围了,所以该思路肯定正确.

然后只要重复k个不同字母到长度n即可.

void solve()
{
    int n,ans;
    cin>>n;
    ans=n;
    for(int i=2;i<=n/2;i++)
    {
        if(n%i==0) a[i]=1;
    }
    for(int i=2;i<n;i++)
    {
        if(a[i]==0)
        {
            ans=i;
            break;
        }
    }
    int x=0;
    for(int i=1;i<=n;i++)
    {
        printf("%c",'a'+x);
        x=(x+1)%ans;
        a[i]=0;
    }
    cout<<endl;
}