[CodeChef-LTIME36]Akhil Recovers The Lost Array

来源:互联网 发布:tensorflow 谷歌 编辑:程序博客网 时间:2024/06/06 11:44

题目大意

给定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;}
0 0
原创粉丝点击