[CodeChef-LTIME36]Akhil Recovers The Lost Array

这是一篇关于CodeChef竞赛中LTIME36的题目解析,讨论如何构造一个整数序列,满足特定的连续子序列和要求。文章介绍了利用数论和前缀和进行构造的方法,并指出需要充分考虑给定的偶数和奇数子序列数量(E和O)。虽然总共有T组数据,但所有序列的元素都限制在0到100之间,且满足E+O=(n+1)*n/2的条件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意

给定nEO,要求构造任意一个整数序列{an}(ai[0,100]),使得该序列有E个连续子序列和为偶数,O个连续子序列和为奇数,其中E+O=(n+1)n2。无解输出1

T组数据,满足n106


题目分析

大家喜闻乐见的数论构造题。
如果单纯地模拟题意,是想不到什么好的解法的。因为这样没用充分利用题目给的EO。我们要考虑怎么使用这两个条件。
既然是对连续子序列和的限制,很容易想到用前缀和来差分一下。设EvenPrefixsum表示偶数前缀和个数,OddPrefixsum表示奇数前缀和个数。
首先显然有

EvenPrefixsum+OddPrefixsum=n+1

注意前缀和包括位置0
然后显然奇数前缀和与偶数前缀和差分才能得到奇数连续子序列,那么就有
EvenPrefixsum×OddPrefixsum=O

那么我们枚举其中一个,就可以利用条件1得到另一个,然后用条件2判断可行性(当然你也可以直接解一元二次方程O(1)判是否有非负整数解)。如果可行,考虑使用这两个信息进行构造。
显然直接在位置EvenPrefixsum填上唯一一个奇数,其余位置填上偶数即可。至此问题完美解决。
时间复杂度O(n)

代码实现

第一次在CC上交题,Submit按钮找了半天。

#include <iostream>
#include <cstdio>
#include <cctype>

using namespace std;

typedef long long LL;

int read()
{
    int x=0,f=1;
    char ch=getchar();
    while (!isdigit(ch)) f=ch=='-'?-1:f,ch=getchar();
    while (isdigit(ch)) x=x*10+ch-'0',ch=getchar();
    return x*f;
}

const int N=1000050;

int T,n,E,O;
LL e,o;

int main()
{
    freopen("alost.in","r",stdin),freopen("alost.out","w",stdout);
    T=read();
    while (T--)
    {
        n=read();
        scanf("%lld %lld",&e,&o);
        for (E=1;E<=n+1;E++)
        {
            O=n+1-E;
            if (1ll*E*O==o) break;
        }
        if (1ll*E*O!=o)
        {
            printf("-1\n");
            continue;
        }
        for (int i=1;i<E;i++) printf("2 ");
        if (E<=n) printf("3 ");
        for (int i=E+1;i<=n;i++) printf("2 ");
        printf("\n");
    }
    fclose(stdin),fclose(stdout);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值