在组合数学上,拉姆齐(Ramsey)定理,又称拉姆齐二染色定理,是要解决以下的问题:要找这样一个最小的数 R(k,l)=n,使得 n 个人中必定有 k 个人相识或 l 个人互不相识。 这个定理以弗兰克·普伦普顿·拉姆齐命名,1930年他在论文On a Problem in Formal Logic(《形式逻辑上的一个问题》)证明了R(3,3)=6。
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.connect(('127.0.0.1', 8888))
defget_recv():# 很奇怪,每次 recv 只能接收到一个字符 r = b'' whileb'party'notin r andb'flag'notin r andb'Correct'notin r andb'Incorrect'notin r: r += s.recv(4096) return r
defnext_char(current: str)->int: whileTrue: right = 0x7E left = 0x20 while left <= right: mid = left + (right - left) // 2 result = verify(f"{current}{chr(mid)}") if result > 0: left = mid + 1 elif result < 0: right = mid - 1 else: break if result != 0: new_char = chr(right) # 当二分结束的时候right指向最后一个smaller left指向第一个bigger current += new_char yield new_char else: yield chr(mid) # 返回 Correct 的时候 mid 就是所需字符 break print(''.join(next_char('')))
稍微有一点细节要注意的就是,由于每次二分的时候没法找到完全相等的位置(text 比 flag 短的时候属于 smaller),因此 right 指针会指向最后一个 smaller 的位置,而 left 会指向第一个 bigger 的位置,这时候 right 指向的字符正好就是 flag 中的字符,因为这时候 smaller 的原因不是字符小而是长度短了。而当返回 Correct 的时候显然 mid 就是 flag 中对应的字符。
后记
所以你说题目背景有什么用呢?
当然是什么鸟用都没啦,不过在我还不知道题目背景的时候我一头扎进了验证拉姆齐数算图论的那个 N 重循环撞得头破血流最后师傅点了下才醒悟。
所以说还是要增加比赛经验呀。
另外这里还存一个疑点,在 dnspy 反编译的结果中出现了很多这样的代码
1 2 3
int num = int.Parse(ClientThread.<Run>g__readline|10_0(ref CS$<>8__locals1)); int num2 = int.Parse(ClientThread.<Run>g__readline|10_0(ref CS$<>8__locals1)); int num3 = int.Parse(ClientThread.<Run>g__readline|10_0(ref CS$<>8__locals1));