zoukankan      html  css  js  c++  java
  • Codeforces Round #648 (Div. 2) G. Secure Password

    题意:

    交互题,给你大小为 (n) 但具体元素未知的数组 (A) ,对应的密码组 (P) 与 数组 (A) 的关系:
    (P_i=A_1|A_2|...|A_{i-1}|A_{i+1}|...|A_n)
    (P_i) 为数组 (A) 中除第 (i) 个元素外,其它所有元素的或;
    现在你有至多 (13) 次询问,每次询问 格式: (?~m~x_1~x_2~...~x_m)
    即询问 数组 (A)(A_{x_1}|A_{x_2}|...|A_{x_m}) 的值;
    最后需要求出密码组 (P)

    分析:

    不是二分,不是二分,不是二分;
    考虑给从数组 (A) 的编号入手

    1. (val[i][0]) 表示编号二进制形式下第 (i) 位为 (0) 的元素的或;
    2. (val[i][1]) 表示编号二进制形式下第 (i) 位为 (1) 的元素的或;

    (举个例子,(val[1][1]=A_1|A_3|A_5...,~因为 1_{(10)}=1_{(2)},3_{(10)}=11_{(2)},5_{(10)}=101_{(2)}))
    所有的编号二进制都是唯一的,所以对应的密码组只要取所有位的反位的元素或就可以了,例如 (5_{(10)}=101_{(2)}) ,那么 (P_5=val[1][0]~|~val[2][1]~|~val[3][0];)
    预处理 (val) 数组,需要的询问是 (2*logn) 次,明显不行,这里借用的是编号的思想,题目的限制询问次数是 (13)(n) 的规模上限是 (1000) ,所以我们从 (13)个二进制位中选择 (6)(1) 位来给数组编号,那么 (C_{13}^6>1000),所以必然可以给每个元素分到唯一的编号,那么就只需要进行刚好 (13) 次询问 (一个二进制位一次) ,然后和上面一样取反位;

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define fi first
    #define sd second
    #define P pair<int,int>
    #define ll long long
    #define pb push_back
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    #define frep(i,a,b) for(int i=a;i>=b;i--)
    const int N = 1000+10;
    ll query(vector<int>G){
    	if(G.empty())return 0;
    	cout<<"? "<<G.size();
    	for(auto v:G)cout<<" "<<v;
    	cout<<endl;
    	fflush(stdout);
    	ll res; cin>>res;
    	return res;
    }
    
    int main()
    {
    	ios::sync_with_stdio(false);
    	cin.tie(0),cout.tie(0);
    	
        vector<int>ask[13];
        int n,m=13,cnt=0,num[N]; cin>>n;
    	rep(i,1,(1<<m)-1){
    		if(__builtin_popcount(i)!=6)continue;
    		num[++cnt]=i;
    		rep(j,0,m-1)if(((i>>j)&1)==0)ask[j].pb(cnt); //取反位询问
    		if(cnt==n)break;
    	}
    	ll w[13],ans[N]={0};
    	rep(i,0,m-1)w[i]=query(ask[i]);
    	
    	rep(i,1,n)rep(j,0,m-1)if((num[i]>>j)&1)ans[i]|=w[j];
    	
    	cout<<"!";
    	rep(i,1,n)cout<<" "<<ans[i];
    }
    
  • 相关阅读:
    SessionFactory Cache 的配置
    乱码处理问题
    格式化当前日期
    JDK的安装
    内存和对象内存池技术在网游开发中的注意点和应用
    Head First设计模式C++实现Strategy模式
    介绍三种将二进制字节字符转换为ASCII方法
    C++风格的类型转换的用法
    i++循环与i循环的执行效率
    系统程序员成长计划组合的威力(一)
  • 原文地址:https://www.cnblogs.com/17134h/p/13089289.html
Copyright © 2011-2022 走看看