标签:ati 逻辑 string clu pre namespace getch 数据规模 情况
[BZOJ2523][Ctsc2001]聪明的学生
试题描述
输入
输出
输入示例
5 8 3 2 2 3 -1? -1
输出示例
3 2 8 6 5 8 3 6 8 2 1 1 1 2 1 2 3 1
数据规模及约定
见“输入”
题解
我是因为喜欢这题题号才做这题的。。。
整个题面有用的话只有最后一句:“总是头上贴着最大的那个数的人最先猜出自己头上的数。”
那么对于一个局面 (x, y, x+y),不妨设 x > y,那么 x+y 那个人能猜出自己脑袋上的数当且仅当他能排除自己脑袋上的数是 x-y 的可能性。怎么排除?就是假设自己脑袋上是 x-y,那么由于他知道另外两个人的数是啥(即 x 和 y),他也知道 x > y,那么就是说 (x, y, x-y) 中最大的是 x,那么如果在轮到头上是 x 的那个人在他理应猜出来的那步时还回答不出来,就说明自己头上的数不可能是 x-y,那么就可以从 (x, y, x-y) 这个局面的答案退出 (x, y, x+y) 这个局面的答案了。
最后我们暴力枚举可能的初始状态然后用迭代代替递归,就 rank 1 了。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cctype> #include <algorithm> using namespace std; int read() { int x = 0, f = 1; char c = getchar(); while(!isdigit(c)){ if(c == ‘-‘) f = -1; c = getchar(); } while(isdigit(c)){ x = x * 10 + c - ‘0‘; c = getchar(); } return x * f; } #define maxn 30010 int nxt[4] = {0, 2, 3, 1}, pre[4] = {0, 3, 1, 2}; struct Tri { int a, b, c; Tri() {} Tri(int _1, int _2, int _3): a(_1), b(_2), c(_3) {} bool operator < (const Tri& t) const { if(a != t.a) return a < t.a; if(b != t.b) return b < t.b; return c < t.c; } } ans[maxn]; bool check(int x, int y, int p, int n) { while(n > 0) { if(x == y) return n == p; if(x > y) { swap(x, y); y -= x; n -= 2; p = nxt[p]; } else { swap(x, y); x -= y; n--; p = pre[p]; } int a[4]; a[p] = x + y; a[nxt[p]] = x; a[pre[p]] = y; } return 0; } int main() { while(1) { int n = read(), s = read(); if(n == -1) break; int p = n % 3 ? n % 3 : 3, cnt = 0; for(int i = 1; i < s; i++) if(check(i, s - i, p, n)) { int a[4]; a[p] = s; a[nxt[p]] = i; a[pre[p]] = s - i; ans[++cnt] = Tri(a[1], a[2], a[3]); } sort(ans + 1, ans + cnt + 1); printf("%d\n", cnt); for(int i = 1; i <= cnt; i++) printf("%d %d %d\n", ans[i].a, ans[i].b, ans[i].c); } return 0; }
标签:ati 逻辑 string clu pre namespace getch 数据规模 情况
原文地址:http://www.cnblogs.com/xiao-ju-ruo-xjr/p/7097205.html