[2019.7.22]BZOJ2523 [Ctsc2001]聪明的学生

第一眼看过去感觉这三个学生都是神仙啊。。。

仔细想想似乎是可以推?

考虑对于一个学生,他一开始知道自己的数字只有至多2种可能。

如果他看到其他两人的数字相等,那么他一定知道自己的数字是两人的数字之和。因为其他两人的数字之差为0,而自己头上的数是正整数。

如果不是,那么他头上的数字就会有2种可能。由于题面告诉我们第一个猜出数字的必然是数字最大的,因此他一定是排除了两者之差的可能。

那么他什么时候会知道呢?

一定是他知道自己头上的数字不是其他两人头上数字之差以后第一次轮到他的时候,设此时的轮数为\(round(a,b,c)\),其中\(a,b,c\)为三人头上的数字。

那么我们考虑他什么时候排除自己头上的数是其他两人之差。

假设\(a>b>c\),那么\(A\)知道自己头上的数字不是\(b-c\),也就是在第\(round(b-c,b,c)\)轮,B没有猜出自己头上的数字。

此时,\(round(a,b,c)=round(b-c,b,c)+2\)

其他5种情况(\(a>c>b\)\(b>a>c\)\(b>c>a\)\(c>a>b\)\(c>b>a\))同理。

于是我们知道\(m\),通过\(n\)能得知谁的数字最大,\(1\)\(m-1\)枚举不是数字最大的人的其中一人的数字,求出这种情况下数字最大这推出自己数字的时间即可。

code:

#include<bits/stdc++.h>
#define ci const int&
using namespace std;
int n,m,bt,a[30010],b[30010],c[30010],sz;
int round(ci x,ci y,ci z){
    if(x==y)return 3;
    if(x==z)return 2;
    if(y==z)return 1;
    int tmp;
    if(x>y&&x>z)return tmp=round(abs(y-z),y,z),tmp%3==0?tmp+1:tmp+2;
    else if(y>x&&y>z)return tmp=round(x,abs(x-z),z),tmp%3==1?tmp+1:tmp+2;
    else return tmp=round(x,y,abs(x-y)),tmp%3==2?tmp+1:tmp+2;
}
int main(){
    while(scanf("%d%d",&n,&m)){
        if(n<0||m<0)return 0;
        bt=(n-1)%3+1,sz=0;
        for(int i=1;i<m;++i){
            if(bt==1){if(round(m,i,m-i)==n)++sz,a[sz]=m,b[sz]=i,c[sz]=m-i;}
            else if(bt==2){if(round(i,m,m-i)==n)++sz,a[sz]=i,b[sz]=m,c[sz]=m-i;}
            else if(round(i,m-i,m)==n)++sz,a[sz]=i,b[sz]=m-i,c[sz]=m;
        }
        printf("%d\n",sz);
        for(int i=1;i<=sz;++i)printf("%d %d %d\n",a[i],b[i],c[i]);
    }
    return 0;
}

转载于:https://www.cnblogs.com/xryjr233/p/BZOJ2523.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值