codeforces#1157D. Ehab and the Expected XOR Problem(构造)

题目链接:

http://codeforces.com/contest/1174/problem/D

题意:

构造一个序列,满足以下条件

  • 他的所有子段的异或值不等于$x$
  • $1 \le a_i<2^n$

输出一个最长的这样的序列

数据范围:

$1 \le n \le 18$
$1 \le x<2^{18}$

分析: 

比赛的时候搞混$subsegment$和$subsequence$,前者为子段一定要连续,后者为子序列可以不连续

赛后看的官方题解

假设构造的序列为$a_i$,它的前缀异或和为$b_i$

即:$b_i=a_1\bigoplus a_2 \bigoplus a_3\bigoplus a_4.....\bigoplus a_i$

$b_i$必须满足以下条件

  • 没有重复的元素即$b_i\neq b_j$
  • 没有一对元素的异或值为$x$
  • 里面没有$x$

关于第二条,我们可以知道,如果$g$加入在$b$数组中,那么$g\bigoplus x$不在$b$数组中,所以这两个数选其中之一就行

得到b数组之后$a_i=b_i \oplus b_{i-1}$

ac代码:

#include<bits/stdc++.h>
#define ll long long
#define pa pair<int,int>
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const ll mod=998244353;
int ans[maxn];
inline ll cal(int st,int len)
{
    return (ll)len*(2*st+len-1)/2;
}
int main()
{
    int n,k;
    while(scanf("%d %d",&n,&k)==2)
    {
        if(cal(1,k)>n)
        {
            printf("NO\n");
            continue;
        }
        if(n==4&&k==2)
        {
            printf("NO\n");
            continue;
        }
        else if(n==8&&k==3)
        {
            printf("NO\n");
            continue;
        }
        int st=1,en=n;
        while(st!=en)
        {
            int md=(st+en)/2;
            if(cal(md+1,k)<=n)st=md+1;
            else en=md;
        }
        for(int i=1;i<=k;i++)
            ans[i]=st+i-1;
        int now=n-cal(st,k),inde=k;
        while(now)
        {
            if(ans[inde]+1<=2*ans[inde-1])ans[inde]++,inde--,now--;
            else inde=k;
        }
        printf("YES\n");
        for(int i=1;i<=k;i++)
        {
            printf("%d",ans[i]);
            if(i==k)printf("\n");
            else printf(" ");
        }
    }
    return 0;
}

  

  

猜你喜欢

转载自www.cnblogs.com/carcar/p/10915459.html