[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;
}
posted @ 2019-07-23 10:30  xryjr233  阅读(284)  评论(2编辑  收藏  举报