题目链接

题目大意:有三个人,头上分别有三个正整数,最大的数等于最小的两个数之和。每个人只能看到另外两个人头上的数字。假设三人绝顶聪明,从第一个人开始轮流回答是否已经猜出了自己头上的数。给定 \(n,m\),问所有方案使得前 \(n - 1\) 轮没人猜出,而在第 \(n\) 轮,应该回答问题的那个人猜出了自己头上的数字为 \(m\)

思维


分析:

样例 1 1 22 3 1 应该还是比较有提示作用的

首先只要有两个数字相同,那么另一个人就可以猜出自己的数是它们的和(因为没有 \(0\)

其他情况,我们用 2 3 1 为例,\(3\) 会在第 \(2\) 轮猜出答案。

轮到 \(3\) 时,它发现自己有 \(2\) 种情况,要么是 \(1\),要么是 \(3\)

而如果自己是 \(1\) 的话,那么 2 1 1\(2\) 会在第 \(1\) 轮猜出答案。所以自己只能是 \(3\)

那么我们设 \(f(a,b,c)\) 表示三个人的数字,从头开始猜,需要多少轮有人可以猜出来。

转移的话就直接人类智慧讨论即可,每次将最大的数变为另外两个的差的绝对值,边界条件就是有两数相等。

\(f(a,b,c) \quad a \geq b \geq c\) 为例

假设我们已经知道了 \(f(b - c,b,c)\) 的值,那么它的 \(b\) 是最大值

\(f(a,b,c)\)\(a\) 是最大值

所以 \(f(a,b,c) = f(b-c,b,c)+2\)

其他的看代码就可以了,有两份,注释的是原来写的,没注释的是惨遭卡常之后,参考 AC 代码大力讨论每一种情况

输出方案直接枚举,计算需要的轮数判断一下就可以了

计算轮数的时候应该剪枝,才能保证单次是 \(O(nm)\)

//-std=c++11
#include <cstdio>
#include <cctype>
#include <vector>
#include <algorithm>
using namespace std;
struct IO{//-std=c++11,with cstdio and cctype
	private:
		static constexpr int ibufsiz = 1 << 20;
		char ibuf[ibufsiz + 1],*inow = ibuf,*ied = ibuf;
		static constexpr int obufsiz = 1 << 20;
		char obuf[obufsiz + 1],*onow = obuf;
		const char *oed = obuf + obufsiz;
	public:
		inline char getchar(){
			#ifndef ONLINE_JUDGE
				return ::getchar();
			#else
				if(inow == ied){
					ied = ibuf + sizeof(char) * fread(ibuf,sizeof(char),ibufsiz,stdin);
					*ied = '\0';
					inow = ibuf;
				}
				return *inow++;
			#endif
		}
		template<typename T>
		inline void read(T &x){
			static bool flg;flg = 0;
			x = 0;char c = getchar();
			while(!isdigit(c))flg = c == '-' ? 1 : flg,c = getchar();
			while(isdigit(c))x = x * 10 + c - '0',c = getchar();
			if(flg)x = -x;
		}
		template <typename T,typename ...Y>
		inline void read(T &x,Y&... X){read(x);read(X...);}
		inline int readi(){static int res;read(res);return res;}
		inline long long readll(){static long long res;read(res);return res;}
		
		inline void flush(){
			fwrite(obuf,sizeof(char),onow - obuf,stdout);
			fflush(stdout);
			onow = obuf;
		}
		inline void putchar(char c){
			#ifndef ONLINE_JUDGE
				::putchar(c);
			#else
				*onow++ = c;
				if(onow == oed){
					fwrite(obuf,sizeof(char),obufsiz,stdout);
					onow = obuf;
				}
			#endif
		}
		template <typename T>
		inline void write(T x,char split = '\0'){
			static unsigned char buf[64];
			if(x < 0)putchar('-'),x = -x;
			int p = 0;
			do{
				buf[++p] = x % 10;
				x /= 10;
			}while(x);
			for(int i = p;i >= 1;i--)putchar(buf[i] + '0');
			if(split != '\0')putchar(split);
		}
		inline void lf(){putchar('\n');}
		~IO(){
			fwrite(obuf,sizeof(char),onow - obuf,stdout);
		}
}io;

int n,m;
inline int f(const int a,const int b,const int c,int sum){
	if(sum > n)return -0x7fffffff;
	if(a == b)return 3;
	else if(b == c)return 1;
	else if(a == c)return 2; 
	else if(a >= b && b >= c)return f(b - c,b,c,sum + 2) + 2;	
	else if(a >= b && a <= c)return f(a,b,a - b,sum + 2) + 2;
	else if(a >= c && a <= b)return f(a,a - c,c,sum + 1) + 1;
	else if(b >= c && c >= a)return f(a,c - a,c,sum + 2) + 2;
	else if(c >= b && b >= a)return f(a,b,b - a,sum + 1) + 1;
	else if(a >= c && c >= b)return f(c - b,b,c,sum + 1) + 1;
}
// inline int f(const int a,const int b,const int c){
// 	if(a == b)return 3;
// 	if(a == c)return 2;
// 	if(b == c)return 1;
// 	const int mx = max({a,b,c});
// 	if(a == mx){
// 		const int t = f(abs(b - c),b,c),rem = t % 3;
// 		if(rem == 1)return t;
// 		if(rem == 2)return t + 2;
// 		if(rem == 0)return t + 1;	
// 	}
// 	if(b == mx){
// 		const int t = f(a,abs(a - c),c),rem = t % 3;
// 		if(rem == 1)return t + 1;
// 		if(rem == 2)return t;
// 		if(rem == 0)return t + 2;
// 	}
// 	if(c == mx){
// 		const int t = f(a,b,abs(a - b)),rem = t % 3;
// 		if(rem == 1)return t + 2;
// 		if(rem == 2)return t + 1;
// 		if(rem == 0)return t;
// 	}
// }
struct node{int a,b,c;};
vector<node> ans;
int main(){
	while(io.read(n,m),(n != -1 && m != -1)){
		int pos,p1,p2;const int rem = n % 3;
		if(rem == 0)pos = 3,p1 = 1,p2 = 2;
		if(rem == 1)pos = 1,p1 = 2,p2 = 3;
		if(rem == 2)pos = 2,p1 = 1,p2 = 3;
		auto get = [pos,p1,p2](const int x,const int i){
			if(x == pos)return m;
			if(x == p1)return i;
			if(x == p2)return m - i;
		};
		ans.clear();
		for(int i = 1;i < m;i++)
			if(f(get(1,i),get(2,i),get(3,i),0) == n)ans.push_back(node{get(1,i),get(2,i),get(3,i)});
		io.write(ans.size(),'\n');
		for(auto x : ans)
			io.write(x.a,' '),io.write(x.b,' '),io.write(x.c,'\n');
	}
	return 0;
}

相关文章:

  • 2022-12-23
  • 2021-08-11
  • 2021-12-17
  • 2021-08-11
  • 2022-12-23
  • 2021-12-16
  • 2021-06-27
  • 2021-09-12
猜你喜欢
  • 2021-11-01
  • 2022-01-15
  • 2021-10-13
  • 2022-12-23
  • 2021-07-07
  • 2022-01-16
  • 2022-12-23
相关资源
相似解决方案