Codeforces Round #435 (Div. 2) c+d

C:给n和k要求,找出n个不同的数,使得亦或起来等于k

可以先预处理从1到1e5,找亦或起来等于(11111111111111111)(二进制)的所有对数,然后四个一起亦或就是0了,再和k亦或

可以看出要分四种情况讨论,对于n%4=p的情况,应该找到p-1个不同的数亦或起来等于0,可以小范围的p-1重循环搜索,对于n%4==2&&x==0的情况要注意特判,可以用6重循环,每层不超过10

代码过于复杂了,应该可以简化一下

#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1

using namespace std;

const double g=10.0,eps=1e-7;
const int N=200000+10,maxn=60000+10,inf=0x3f3f3f;

bool vis[N];
int main()
{
  //  cout<<(0^1^2^4^8^15)<<endl;
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n,x;
    cin>>n>>x;
    if(n==2&&x==0)
    {
        cout<<"NO"<<endl;
        return 0;
    }
    cout<<"YES"<<endl;
    vector<int>v1,v2;
    for(int i=1;i<(1<<17);i++)
    {
        int s=0;
        for(int j=0;j<17;j++)
        {
            if(i&(1<<j));
            else s+=(1<<j);
        }
       // cout<<i<<" "<<s<<endl;
        if(!vis[i]&&!vis[s])
        {
            vis[s]=vis[i]=1;
            v1.pb(i);
            v2.pb(s);
        }
    }
    if(n%4==2&&x==0)
    {
        set<int>ans;
        int a,b,c,d,e,f;
        for(int i=0;i<30;i++)
        {
            for(int j=i+1;j<30;j++)
            {
                for(int k=j+1;k<30;k++)
                {
                    for(int ii=k+1;ii<30;ii++)
                    {
                        for(int jj=ii+1;jj<30;jj++)
                        {
                            if((i^j^k^ii^jj)!=i&&(i^j^k^ii^jj)!=j
                               &&(i^j^k^ii^jj)!=k&&(i^j^k^ii^jj)!=ii
                               &&(i^j^k^ii^jj)!=jj&&(i^j^k^ii^jj)==0)
                            {
                                ans.insert(i);
                                ans.insert(j);
                                ans.insert(k);
                                ans.insert(ii);
                                ans.insert(jj);
                                ans.insert(0);
                                a=i,b=j,c=k,d=ii,e=jj,f=0;
                                break;
                            }
                        }
                        if(ans.size()!=0)break;
                    }
                    if(ans.size()!=0)break;
                }
                if(ans.size()!=0)break;
            }
            if(ans.size()!=0)break;
        }
        int k=0;
        for(int i=0;i<v1.size();i++)
        {
            if(k>=(n-6)/2)break;
            if(v1[i]==a||v2[i]==a||v1[i]==b||v2[i]==b||
               v1[i]==c||v2[i]==c||v1[i]==d||v2[i]==d||
               v1[i]==e||v2[i]==e||v1[i]==f||v2[i]==f)continue;
            k++;
            ans.insert(v1[i]);
            ans.insert(v2[i]);
        }
        for(auto x:ans)
            cout<<x<<" ";
        cout<<endl;
        return 0;
    }
    set<int>ans;
    if(n%4==1)
    {
        ans.insert(x);
        int k=0;
        for(int i=0;i<v1.size();i++)
        {
            if(k>=(n-1)/2)break;
            if(v1[i]==x||v2[i]==x)continue;
            ans.insert(v1[i]);
            ans.insert(v2[i]);
            k++;
        }
    }
    else if(n%4==2)
    {
        int a,b;
        for(int i=0;i<100;i++)
        {
          //  cout<<(x^i)<<"  "<<i<<endl;
            if((x^i)!=i)
            {
              //  cout<<(x^i)<<" "<<i<<endl;
                ans.insert(x^i);
                ans.insert(i);
                a=x^i;b=i;
                break;
            }
        }
        int k=0;
        for(int i=0;i<v1.size();i++)
        {
            if(k>=(n-2)/2)break;
            if(v1[i]==a||v2[i]==a||v1[i]==b||v2[i]==b)continue;
            ans.insert(v1[i]);
            ans.insert(v2[i]);
            k++;
        }
    }
    else if(n%4==3)
    {
        int a,b,c;
        for(int i=1;i<100;i++)
        {
            for(int j=i+1;j<100;j++)
            {
                if((x^i^j)!=i&&(x^i^j)!=j)
                {
                    ans.insert(x^i^j);
                    ans.insert(i);
                    ans.insert(j);
                    a=x^i^j;b=i;c=j;
                    break;
                }
            }
            if(ans.size()!=0)break;
        }
        int k=0;
        for(int i=0;i<v1.size();i++)
        {
            if(k>=(n-3)/2)break;
            if(v1[i]==a||v2[i]==a||v1[i]==b||v2[i]==b||v1[i]==c||v2[i]==c)continue;
            ans.insert(v1[i]);
            ans.insert(v2[i]);
            k++;
        }
    }
    else
    {
        int a,b,c,d;
        for(int i=1;i<100;i++)
        {
            for(int j=i+1;j<100;j++)
            {
                for(int k=j+1;k<100;k++)
                {
                    if((x^i^j^k)!=i&&(x^i^j^k)!=j&&(x^i^j^k)!=k)
                    {
                        ans.insert(x^i^j^k);
                        ans.insert(i);
                        ans.insert(j);
                        ans.insert(k);
                        a=x^i^j^k;b=i;c=j;d=k;
                        break;
                    }
                }
                if(ans.size()!=0)break;
            }
            if(ans.size()!=0)break;
        }
        int k=0;
        for(int i=0;i<v1.size();i++)
        {
            if(k>=(n-4)/2)break;
            if(v1[i]==a||v2[i]==a||v1[i]==b||v2[i]==b||v1[i]==c||v2[i]==c||v1[i]==d||v2[i]==d)continue;
            ans.insert(v1[i]);
            ans.insert(v2[i]);
            k++;
        }
    }
    for(auto x : ans)
        cout<<x<<" ";
    cout<<endl;
    return 0;
}
/********************

********************/

C

D:交互题(永远是二分),有一个长度为n的01字符串,先输入n,查询是?+长度为n的01字符串,给出的结果是汉明距离(两个字符串不同的个数),要求在15次内找到一个0一个1

既然能保证有0和1,那么可以找到01串或者10串,用二分对于[m,r)如果有01串,那么l=m,否则r=m

one是1的个数,那么如何判断是否有01串呢,构造一个l到r是1的,其他都是0的字符串,假如l到r中只有0,那么结果就是one+(r-l+1),如果只有1,那么结果就是one-(r-l+1),这样有01就是one-(r-l+1)<k<one+(r-l+1)

#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1

using namespace std;

const double g=10.0,eps=1e-7;
const int N=100000+10,maxn=60000+10,inf=0x3f3f3f;

void debug(){cout<<-1<<endl;}

int n,one;
bool ok(int l,int r)
{
    string s=string(n,‘0‘);
    for(int i=l;i<=r;i++)
        s[i]=‘1‘;
    cout<<"? "<<s<<endl;
    cout.flush();
    int a;
    cin>>a;
    return one-(r-l+1)<a&&a<one+(r-l+1);
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n;
    cout<<"? "<<string(n,‘0‘)<<endl;
    cout.flush();
    cin>>one;
    int l=0,r=n-1;
    while(l<r-1)
    {
        int m=(l+r)/2;
        if(ok(m,r))l=m;
        else r=m;
    }
    string s=string(n,‘0‘);
    s[l]=‘1‘;
    cout<<"? "<<s<<endl;
    cout.flush();
    int a;
    cin>>a;
    if(a==one+1)cout<<"! "<<l+1<<" "<<l+2<<endl;
    else cout<<"! "<<l+2<<" "<<l+1<<endl;
    cout.flush();
    return 0;
}
/********************
0011001100
********************/

D

时间: 2024-07-30 11:52:41

Codeforces Round #435 (Div. 2) c+d的相关文章

Codeforces Round #435 (Div. 2) D. Mahmoud and Ehab and the binary string[二分]

题目:http://codeforces.com/problemset/problem/862/D 题意:交互题,询问15次以内Hamming distance,输出一个二进制串里任意一个0或1的位置 题解:极简单的二分,从最后一位先判断一个,然后二分 根据上次和本次的距离差是否等于二分长度判断在左端还是右端有需要寻找的值寻找另一个. 1 #define _CRT_SECURE_NO_DEPRECATE 2 #pragma comment(linker, "/STACK:102400000,10

D. Mahmoud and Ehab and the binary string Codeforces Round #435 (Div. 2)

http://codeforces.com/contest/862/problem/D 询问题 fflush(stdout) 调试: 先行给出结果,函数代替输入 1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <time.h> 6 #include <string> 7 #include <se

E. Mahmoud and Ehab and the function Codeforces Round #435 (Div. 2)

http://codeforces.com/contest/862/problem/E 二分答案 一个数与数组中的哪个数最接近: 先对数组中的数排序,然后lower_bound 1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <time.h> 6 #include <string> 7 #includ

Codeforces Round #435 (Div. 2) E. Mahmoud and Ehab and the function(预处理+二分)

题目链接:点我点我 题意:公式:,给出n个数,从a[1]到a[n],和m个数(b数组),然后从b数组里挑出连续的n个数(也就m-n+1中选择),按公式计算,使得f最小, 还有q次对a数组的操作(某个区间增加值,减少值),求出最小值. 题解:显然对a数组的处理非常简单,一开始确定一定值,然后update的时候,判断一下奇偶性质就可以直接加了(前一项正后一项一定是负的,可以抵消). 然后就是b数组的处理了,一开始没处理好,一直在这边卡超时.先把b数组一项一项正负不同的加进去,然后再进行处理,得到c数

Codeforces Round #428 (Div. 2)

Codeforces Round #428 (Div. 2) A    看懂题目意思就知道做了 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i

Codeforces Round #424 (Div. 2) D. Office Keys(dp)

题目链接:Codeforces Round #424 (Div. 2) D. Office Keys 题意: 在一条轴上有n个人,和m个钥匙,门在s位置. 现在每个人走单位距离需要单位时间. 每个钥匙只能被一个人拿. 求全部的人拿到钥匙并且走到门的最短时间. 题解: 显然没有交叉的情况,因为如果交叉的话可能不是最优解. 然后考虑dp[i][j]表示第i个人拿了第j把钥匙,然后 dp[i][j]=max(val(i,j),min(dp[i-1][i-1~j]))   val(i,j)表示第i个人拿

Codeforces Round #424 (Div. 2) C. Jury Marks(乱搞)

题目链接:Codeforces Round #424 (Div. 2) C. Jury Marks 题意: 给你一个有n个数序列,现在让你确定一个x,使得x通过挨着加这个序列的每一个数能出现所有给出的k个数. 问合法的x有多少个.题目保证这k个数完全不同. 题解: 显然,要将这n个数求一下前缀和,并且排一下序,这样,能出现的数就可以表示为x+a,x+b,x+c了. 这里 x+a,x+b,x+c是递增的.这里我把这个序列叫做A序列 然后对于给出的k个数,我们也排一下序,这里我把它叫做B序列,如果我

[Codeforces] Round #352 (Div. 2)

人生不止眼前的狗血,还有远方的狗带 A题B题一如既往的丝帛题 A题题意:询问按照12345678910111213...的顺序排列下去第n(n<=10^3)个数是多少 题解:打表,输出 1 #include<bits/stdc++.h> 2 using namespace std; 3 int dig[10],A[1005]; 4 int main(){ 5 int aa=0; 6 for(int i=1;;i++){ 7 int x=i,dd=0; 8 while(x)dig[++dd

Codeforces Round #273 (Div. 2)

Codeforces Round #273 (Div. 2) 题目链接 A:签到,仅仅要推断总和是不是5的倍数就可以,注意推断0的情况 B:最大值的情况是每一个集合先放1个,剩下都丢到一个集合去,最小值是尽量平均去分 C:假如3种球从小到大是a, b, c,那么假设(a + b) 2 <= c这个比較明显答案就是a + b了.由于c肯定要剩余了,假设(a + b)2 > c的话,就肯定能构造出最优的(a + b + c) / 3,由于肯定能够先拿a和b去消除c,而且控制a和b成2倍关系或者消除