Codeforces Round #685 (Div. 2) (D(博弈) E1 E2(交互))

题目:D
题意:A和U玩游戏,起始点坐标在(0,0),每一轮玩家选择将x或者y的值增加k(一定需要增加),保持增加后(p,q)距离 p 2 + q q < = d 2 p^2+q^q<=d^2 p2+qq<=d2。谁最后不能操作谁输,输出胜利者。

画图可以发现,以k为单位划方格,无论A先手怎么走,后手可以走成一个方格,完全被包含 ( x ∗ k ) 2 (x*k)^2 xk2的正方形,后手都掌握了必胜走法,连续走两格子就改变了奇偶的。由于 2 ∗ x 2*x 2x必为偶数,先手必败,只需要判断一下(x+1)k是否存在。

#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
//#include<unordered_map>
#include<map>
#include<algorithm>
#include<queue>
#define mmp make_pair
#define inf 0x3f3f3f3f
#define llinf 0x7fffffffffffffff
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
typedef double ld;
const ll mod=1e9+7;
const int maxn=2e5+10;
int main() {
    int T;
    scanf("%d",&T);
    while(T--) {
        ll d,k;
        scanf("%lld %lld",&d,&k);
        if(d==k) {
            printf("Ashish\n");
            continue;
        }
        ll ans;
        for(ll i=1;;++i) {
            if(i*i*k*k*2>d*d) {
                ans=i-1;
                break;
            }
        }
        k*=k;
        if(((ans*ans*k)+(ans+1)*(ans+1)*k)<=d*d) {
            printf("Ashish\n");
        }
        else printf("Utkarsh\n");
    }
    return 0;
}

题目:E1
交互题,给定n长度的序列让你还原,你每次可以询问^,|,&,两个位置给出的位运算结果。询问不能超过n+2次。

a + b = a a+b=a a+b=a^ b + ( a & b ) < < 1 b+(a\&b)<<1 b+(a&b)<<1,与操作就相当于进位,这么表示完之后就可以解给方程组。
但是前3个解完需要6+n-3=n+3次,还必须化简一重,a[1]^a[2] , a[1]^a[3] , 那么我们不用询问2和3的异或了,直接把前两次答案异或一下。
其余的直接通过1解得。

#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
//#include<unordered_map>
#include<map>
#include<algorithm>
#include<queue>
#define mmp make_pair
#define inf 0x3f3f3f3f
#define llinf 0x7fffffffffffffff
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
typedef double ld;
const ll mod=1e9+7;
const int maxn=2e5+10;
int a[75536];
int main() {
 //   freopen("input.txt", "r", stdin);
    int n,i;
    scanf("%d",&n);
    int x,y,z;int x1,x2,x3,x4;
    cout<<"XOR"<<" "<<1<<" "<<2<<endl;
    fflush(stdout);
    scanf("%d",&x1);
    cout<<"AND"<<" "<<1<<" "<<2<<endl;        fflush(stdout);
    scanf("%d",&x2);
    x=x1+x2*2;
    cout<<"XOR"<<" "<<1<<" "<<3<<endl;        fflush(stdout);
    scanf("%d",&x3);
    cout<<"AND"<<" "<<1<<" "<<3<<endl;        fflush(stdout);
    scanf("%d",&x4);
    y=x3+x4*2;
    x1=x1^x3;
    cout<<"AND"<<" "<<2<<" "<<3<<endl;        fflush(stdout);
    scanf("%d",&x2);
    z=x1+x2*2;
    a[1]=(y-z+x)/2;
    a[2]=x-a[1];
    a[3]=z-a[2];
    for(i=4;i<=n;++i) {
        cout<<"XOR"<<" "<<1<<" "<<i<<endl;        fflush(stdout);
        scanf("%d",&x1);
        a[i]=x1^a[1];
    }
    cout<<"!";
    for(int i=1;i<=n;++i) {
       cout<<" "<<a[i];
    }
    cout<<endl;
    fflush(stdout);
  //  fclose(stdin);
    return 0;
}

题目:E2
唯一差别在不能超过n-1次询问。
还有一个条件题目注上了黑体。。。。。
在这里插入图片描述
范围在[0,n-1]。
用a[1]去异或并记录,
如果没有全部用必有相同的,那么两个等式或者一个就可以求解。
继续如果没有一个相同的证明有n-1个不同的数,判断一个异或的结果是否有0,有的话a[1]与其相等,&操作即可。

否则寻找n-1,异或出的n-1必然a[1]+a[i]=n-1,任意拉上一个位置求解方程。

#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
//#include<unordered_map>
#include<map>
#include<algorithm>
#include<queue>
#define mmp make_pair
#define inf 0x3f3f3f3f
#define llinf 0x7fffffffffffffff
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
typedef double ld;
const ll mod=1e9+7;
const int maxn=2e5+10;
int a[75536];
int book[maxn];
int X[75535];
int main() {
    memset(book,0,sizeof(book));
    int n;
    scanf("%d",&n);
    int pos1=-1,pos2=-1;
    for(int i=2;i<=n;++i) {
        printf("XOR 1 %d\n",i);
        fflush(stdout);
        int x;
        scanf("%d",&x);
        X[i]=x;
        if(pos1!=-1) continue;
        if(book[x]==0) {
            book[x]=i;
        }
        else {
            pos1=book[x];
            pos2=i;
        }
    }
    if(pos1!=-1) {
        int x2;
        printf("AND 1 %d\n",pos1); fflush(stdout);
        scanf("%d",&x2);
        int x=x2*2+X[pos1];
        printf("AND %d %d\n",pos1,pos2); fflush(stdout);
        scanf("%d",&a[pos1]);
        a[1]=x-a[pos1];
    }
    else {
        int f=-1;
        for(int i=2;i<=n;++i) {
            if(X[i]==0) {
                f=i;
                break;
            }
        }
        if(f!=-1) {
            printf("AND 1 %d\n",f); fflush(stdout);
            int temp; scanf("%d",&temp);
            a[1]=a[f]=temp;
        }
        else {
            int ff;
            f=book[n-1];
            ff=( (f==2) ? 3 : 2 );
            int xx,yy;
            // 1 f ff
            printf("AND 1 %d\n",ff); fflush(stdout);
            scanf("%d",&xx);
            int x=xx*2+X[ff];
            printf("AND %d %d\n",f,ff); fflush(stdout);
            scanf("%d",&yy);
            int y=yy*2+(X[f]^X[ff]);
            a[1]=(x-y+n-1)/2;
        }
    }
    printf("! %d",a[1]);
    for(int i=2;i<=n;++i) {
        printf(" %d",X[i]^a[1]);
    }
    fflush(stdout);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值