zoukankan      html  css  js  c++  java
  • 题解 P5779 【[CTSC2001]聪明的学生】

    题目链接

    Solution [CTSC2001]聪明的学生

    题目大意:有三个人,头上分别有三个正整数,最大的数等于最小的两个数之和。每个人只能看到另外两个人头上的数字。假设三人绝顶聪明,从第一个人开始轮流回答是否已经猜出了自己头上的数。给定 (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 = '';
    					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 = ''){
    			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 != '')putchar(split);
    		}
    		inline void lf(){putchar('
    ');}
    		~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(),'
    ');
    		for(auto x : ans)
    			io.write(x.a,' '),io.write(x.b,' '),io.write(x.c,'
    ');
    	}
    	return 0;
    }
    
  • 相关阅读:
    redis命令参考(四) set集合
    redis命令参考(三) List列表相关
    redis命令参考(二)
    redis命令参考(一) SortedSet相关
    insert_into_on_dumplicate_key
    laravel深入分析
    开发中GBK+UTF8编码的处理
    ajax封装调用
    linux正则表达式的用法
    linux 如何保证使程序后台运行(nohup &)
  • 原文地址:https://www.cnblogs.com/colazcy/p/14043376.html
Copyright © 2011-2022 走看看