目录
〇,自我指涉
https://blog.csdn.net/nameofcsdn/article/details/104848261
一,谓词逻辑推理
1,推理过程的泛化
谓词逻辑推理,都可以泛化成这样的形式:
给出一些句子,每个句子都可以抽象成一个谓词公式(谓词公式包括原子谓词公式),根据语义+常识(公理)可以提炼出一些谓词公式之间的关系,再加上题目给的谓词公式之间的关系,推导出部分谓词公式的恒定值,或者关于这些谓词公式的某个代数式的最值等等。
PS:
谓词公式之间的关系可以有很多形式,比如若A则B,比如ABC里面至少有2个位true,比如若ABCDEFG里面至少有3个为true,则EFGH要么全true要么全false,等等等等。。。。
PS:
下文《三个人比大小》中有严格按照谓词逻辑的理论进行推理的示例。
2,谓词逻辑推理puzzle分类
按照输入条件的形式,可以分为普通逻辑、组合逻辑、自我指涉的逻辑。
这里的普通逻辑、组合逻辑都是非自我指涉的,而自我指涉的实际上又可以细分普通逻辑、组合逻辑等等。
组合逻辑中一种常见的特例,就是交叉逻辑。
二,普通逻辑
1,每个人一半真话一半假话
一天小明和小红,小黑后院玩耍,妈妈气冲冲地走过来,质问他们三个谁偷了放在柜子上面的一块钱。
小红说:我没偷,小黑没偷。
小黑说:小红没偷,我没偷。
小明说:我没偷,小红没偷。
已知他们所说的话中有一半是真一半是假,请问是谁偷了?
答案:
小红
2,三个人比大小
甲,乙,丙三人在酒吧摇筛子比点数大小。
甲:我的点数肯定比乙大
乙:我的点数是所有人里最大的
丙:我的点数是所有人里最大的。
只有一个人说了假话,请问三个人的大小关系?
答案:丙
泛化的求解思路:
(1)原子谓词公式
A表示甲>乙,B表示乙>甲,C表示乙>丙,D表示丙>甲,E表示丙>乙
(2)谓词公式
甲的谓词公式是x=A,乙的谓词公式是y=B&C,丙的谓词公式是z=D&E
“只有一个人说了假话”的谓词公式是(!x&y&z)|(x&!y&z)|(x&y&!z)
(3)谓词公式之间的关系
根据常识(公理)可得,A&B=false, C&E=false,
题目又说(!x&y&z)|(x&!y&z)|(x&y&!z)=true
(4)演算
因为x&y=A&B&C=false,y&z=B&C&D&E=false
又有(!x&y&z)|(x&!y&z)|(x&y&!z)=true
所以x=true,y=false,z=true
所以A=true,D=true,即丙>甲>乙。
3,两个人的成绩
小蓝和小黄是好朋友。
有一次,有人问她们‘你们谁的成绩好?’
小蓝说‘我的成绩比较好一些。’
小黄说‘我的成绩比较差一些。’
她们俩至少有一人没说实话。 那么到底谁的成绩好?(已知他们成绩不一样)
答案:小黄
三,交叉逻辑
仅以此游戏(交叉逻辑益智游戏)代表大量同类puzzle。
规则
简单关卡
困难关卡
四,组合逻辑
1,宿舍人数
某宿舍住着若干个研究生,其中一个是黑龙江人,两个是北方人,一个是云南人, 两个人这学期只选修了逻辑哲学,三个人这学期选修古典音乐欣赏。
假设以上的介绍涉及了这宿舍中所有的人,那最少可能是几个人?最多可能是几个人?
答案:
最少5个,最多8个
五,自我指涉的逻辑
1,二难悖论
二难悖论参考经典悖论
2,二难推理
把不出现二难悖论作为条件的逻辑推理,叫二难推理,也叫自我指涉的逻辑推理。
二难推理大概分2大类,一类是和说真话说假话有关,一类是和选择题有关。这2类都可以用谓词逻辑去推理,比如当A为false时,“如果A则B”就是个真命题。
3,指涉环
真话假话问题,自我指涉的方式往往是,陈述内容形如“***是说真话的”,直接形成二难推理。
而选择题类的问题,自我指涉的方式往往是,A陈述内容形如“B陈述内容是错误的”,而B又指向C,C又指向A,从而形成环。
或者更长的环A->B->C->D->E->A
这个环越长,推理的难度往往越大。
4,真话假话问题
(1)这句话是谁说的
问题:
假如有2个人,一个叫小红一个叫小明,其中一个人一直说真话,另外一个人一直说假话。
有一天其中一个人说,“小红是一直说假话的那个人”,请问这句话是谁说的,是小红还是小明?
答案:
是小明,因为如果是小红说“小红是一直说假话的那个人”,那就构成了二难推理。
PS:我们还是不知道谁是说真话的人。
PS:说假话的那个人,无论他说“我是说假话的那个人”还是说“我这句话是假话”,都是二难推理。
(2)一个说真话的和一个说假话的人
如果有一个说真话的和一个说假话的人在一起,怎么样用1个是非问答题区分他们?
PS:每个人对提问都要尝试回答,回答的答案只涉及是和否,下同。
如果问,你是说真话的吗,或者问,你是说假话的吗?那么2人回答一致,无法区分。
如果问,你会回答否吗?那么说真话的人无法回答,说假话的人回答是或者否都可以。
(3)3个盒子
有红、绿、蓝三个盒子,其中只有一个盒子装有奖品。毎个盒子上有一句话。
红色盒子:奖品在蓝色盒子中。
绿色盒子:奖品不在红色盒子中。
蓝色盒子:奖品在绿色盒子中。
已知装有奖品的盒子上的话都是假话,没有奖品的盒子上的话都是真话。则奖品在哪个盒子中?
答案:
蓝色盒子
(4)三种人
这里所有人要么是只说真话的君子,要么是只说假话的小人,要么是有时说真话,有时说假话的凡夫。
其中等级从高到低君子,凡夫,小人。
a:我的等级不是最高的
b:我的等级比e高
c:b说的是对的
d:我和b的等级一样高
e:我不是等级最低的
f:g和a的等级一样高
g:h比我的等级高
h:我不比f的等级高
i:f比我的等级低或者我是个小人
已知gi不会都是凡夫,且这9个人里有且只有四个凡夫。那么b的身份是什么?
答案:
(1)我们推出a是凡夫。
(2)我们推出g是凡夫,f是君子或凡夫,i是君子或小人。
那么此时剩下还可以利用的信息只剩下:
b:我的等级比e高
c:b说的是对的
d:我和b的等级一样高
h:我不比f的等级高
i:f比我的等级低或者我是个小人
且这里只有四个凡夫。
(3)然后我们推出,f是凡夫,i是君子,h是凡夫。
那么此时剩下还可以利用的信息只剩下:
b:我的等级比e高
c:b说的是对的
d:我和b的等级一样高
且bcde中没有凡夫。
(4)最后我们推出,b是君子,c是君子,e是小人,d是君子或小人
那么此时所有信息都用完了,无矛盾。
(5)三种人三个问题
三个神A、B、C按乱序分别叫做「真实」、「错误」与「随机」。「真实」一直说真话,「错误」一直说假话,但是「随机」说真话或说假话是一件完全随机的事情。
你的任务是通过问3个是与非的问题来确认A、B和C的身份,每一个问题只能问一个神,不同问题可以选择同一个神。每个神只会回答「是」或者「否」。
答案:
问A:这个问题你会回答否吗?
问B:这个问题你会回答否吗?
如果其中有一个人无法回答,那么他就是「真实」,只要问他C是不是「错误」即可。
如果两个人都回答了,无论回答什么都没区别,C就是「真实」,只要问他A是不是「错误」即可。
PS:这个问题,其实是我根据下面的《有史以来最难的逻辑谜题》简化而来,而这个解答的思路也是我在解答《有史以来最难的逻辑谜题》时发现的思路,即想办法让神因为二难悖论而无法回答。
PS:这有点像“上帝啊,你既然说自己是万能的,那我问你,你能不能创造一个连你也搬不动的石头?”
(6)有史以来最难的逻辑谜题
这个谜题是 Smullyan留下的遗产,而这个标题是由麻省理工学院的逻辑哲学家George Boolos所写。
谜题:
三个神A、B、C按乱序分别叫做「真实」、「错误」与「随机」。「真实」一直说真话,「错误」一直说假话,但是「随机」说真话或说假话是一件完全随机的事情。
你的任务是通过问3个是与非的问题来确认A、B和C的身份,每一个问题只能问一个神,不同问题可以选择同一个神。这些神只会回答「da」或者「ya」,但你不知道哪个代表是,哪个代表否。
分析:
根据上面的二难悖论的思路,首先我们很容易想到这4种问题:
问题1:
你会回答「da」,而且「da」表示否,对吗?
如果「da」表示是,则「真实」会回答「ya」,「错误」会回答「da」, 「随机」回答哪个都可以
如果「da」表示否,则「真实」会无法回答, 「错误」回答哪个都可以,「随机」回答哪个都可以
问题2:
你会回答「da」,而且「da」表示是,对吗?
如果「da」表示是,则「真实」回答哪个都可以,「错误」会无法回答, 「随机」回答哪个都可以
如果「da」表示否,则「真实」会回答「da」, 「错误」会回答「ya」,「随机」回答哪个都可以
问题3:
你会回答「da」,而且你是「真实」对吗?
如果「da」表示是,则「真实」回答哪个都可以,「错误」会回答「da」,「随机」回答哪个都可以
如果「da」表示否,则「真实」会无法回答, 「错误」会回答「ya」,「随机」回答哪个都可以
问题4:
你会回答「da」,而且你是「错误」对吗?
如果「da」表示是,则「真实」会回答「ya」,「错误」会无法回答, 「随机」回答哪个都可以
如果「da」表示否,则「真实」会回答「da」,「错误」回答哪个都可以,「随机」回答哪个都可以
然后我们再看看,这4个问题选2个,能得到多少信息。
4个问题一共也就是16种组合,我简单分析了一下,应该是不足以推出答案。
于是我们还需要找出更复杂的问题才行。
问题5:
你是「真实」而且你会回答「da」,或者,你是「错误」而且你会回答「ya」,对吗?
如果「da」表示是,则「真实」回答哪个都可以,「错误」回答哪个都可以,「随机」回答哪个都可以
如果「da」表示否,则「真实」会无法回答, 「错误」会无法回答, 「随机」回答哪个都可以
问题6:
你是「真实」而且你会回答「ya」,或者,你是「错误」而且你会回答「da」,对吗?
如果「da」表示是,则「真实」会无法回答, 「错误」会无法回答, 「随机」回答哪个都可以
如果「da」表示否,则「真实」回答哪个都可以,「错误」回答哪个都可以,「随机」回答哪个都可以
问题7:
你是「真实」而且你会回答否,或者,你是「错误」而且你会回答是,对吗?
「真实」会无法回答, 「错误」会无法回答,「随机」回答哪个都可以
这样,我们终于想出了关键的问题,就是问题7
答案:
问A:你是「真实」而且你会回答否,或者,你是「错误」而且你会回答是,对吗?
问B:你是「真实」而且你会回答否,或者,你是「错误」而且你会回答是,对吗?
由于「真实」和「错误」都无法回答,「随机」回答哪个都可以,所以2次问答之后,就可以确定哪一个是「随机」
剩下的2个,随便选一个,问他:你会回答否,对吗?
由于「真实」会无法回答,「错误」回答哪个都可以,所以就区分开了。
5,选择题
选择题分为单选和多选2种。
单选中一种特殊的场景是判断题,可以理解成是2个选项的单选题,A选项是“...”,B选项是“A是错的”。
(1)单选题
先看看单选题1:
关于本题答案,说法正确的是 ?
A 如果选A那就选B
B 如果选B那就选C
C 如果选C那就选A
D 如果选D那就选D
如果只分析答案,那很容易得出答案是D的结论,但这个答案对吗?
我们从小学到大学做了16年单选题,现在来归纳一下单选题的限制条件:
(1)对于每个选项,如果是对的那就选,如果是错的那就不选
(2)一个题目只选出一个选项,不能多,也不能少
(3)正确答案是唯一的
那么,问题来了,如果选A,那么就不选B,那A的描述就是错的,那就不能选A了。
同理,选B也不行,选C也不行。但是,如果选D,那么根据数理逻辑,A也是对的。
所以说,这个单选题不能同时满足(1)(2),是个不合法的单选题。
再看看单选题2:
本题的答案是?
A 是B
B 是C
C 是A
D 是D
表面上看起来和单选题1差不多,实际上不一样。
这题合法,同时满足(1)(2)(3)答案就是D,虽然题目压根不一样,但是推导出答案是选D的过程却是一模一样。
再看看单选题3:
本题的答案是?
A 是A
B 是B
C 是C
D 是D
这题选ABCD任何中的一个都可以满足(1)(2),所以不满足(3),是个不合法的单选题。
(2)多选题
多选题1:
关于本题答案,说法正确的是___ ?
A 如果选A那就选B
B 如果选B那就选C
C 如果选C那就选A
D 如果选D那就选D
我们同样来归纳一下多选题的限制条件:
(1)对于每个选项,如果是对的那就选,如果是错的那就不选
(2)一个题目最少有一个正确选项,最多全选,一般还默认至少两个正确选项
(3)正确答案只有一个
这样,多选题1满足(1)(2),却不满足(3),正确答案有2个,分别是ABC、ABCD
如果特别说明这个是广义多选题,可以只选一个选项,正确答案仍然是这2个,而只选D不是正确答案。
(3)自我指涉的选择题的偏特化
上文写到了谓词逻辑推理过程的泛化,对于自我指涉的选择题,我们做一个偏特化。
(3.1)自我指涉的选择题,每个题目的每个选项就是1个原子谓词公式,且不存在其他原子谓词公式。
(3.2)如果是单选题,则题目给出的关系就是,一个题目的所有选项中,恰好一个是true,其他的都是false。如果是狭义多选题,则关系就是,一个题目的所有选项中,至少2个是true,至多全是true。如果是广义多选题,则关系就是,一个题目的所有选项中,至少1个是true,至多全是true。
(3.3)每一个选项的内容,都是由这些原子谓词公式组成的一个谓词公式,且值一定和该选项对应的原子谓词公式相等。
(3.4)综上,如果有n个选择题,每个题目的选项数加起来一共是m,则这一套自我指涉的选择题的原子谓词公式数量是m,条件数量是n+m。我们要做的就是根据这n+m个条件推导出这m个变量的值。
(3.5)对于n个判断题,可以进一步偏特化,我们要做的就是根据这n个条件推导出这n个变量的值。
下文的《十条陈述》,有严格按照这套方法进行推理的示例。
六,10个关联的单选题
1,问题
1,十个题中,第几题是第一个选了B的题
A2 B3 C4 D5 E6
2,十个题中,唯一的连续两个具有相同答案的题是
A第23题 B第34题 C第45题 D第56题 E第67题
3,本题和第几题答案相同
A1 B2 C4 D7 E6
4,十个题中,共有几个选A
A0 B1 C2 D3 E4
5,本题和第几题答案相同
A10 B9 C8 D7 E6
6,十个答案中,A的个数和哪个的个数相同
A B B C C D D E E以上都不是
7,本题答案和下题答案相差几个字母(如A和C相差2个)
A4 B3 C2 D1 E0
8,十个答案中,A和E共有几个
A2 B3 C4 D5 E6
9,十个答案中,B和C和D共有几个
A某个质数 B某个阶乘数 C平方数 D立方数 E5的倍数
10,本题的答案是
A A B B C C D D E E
这10个题目和一般的单选题不太一样,这10个题目要求给出每个题目选什么,才能满足互相的约束条件。
比如说,如果第3题选A,那么因为A是1,所以必须满足第3题和第1题的答案相同。
同时,因为BCDE分别是2467,所以第2467题的答案都不同于第3题。
也就是说,如果第1题选A,第2题选B,那么第3题选A或B都行。
(这一点需读者细细品味)
2,逻辑化简
为了简化编程工作,同时提高计算效率,可以先用逻辑推理做一些简化。
(1)单独看第7题
7,本题答案和下题答案相差几个字母(如A和C相差2个)
A4 B3 C2 D1 E0
这个题目可以等价代替为
7,下题答案是
A E B E C A或E D C或E E E
进一步,可以代替为
7,下题答案是
A × B × C A D C E ×
×表示已经确定了不会选这个选项
值得注意的是,并不是每个确定不选的选项都可以用×表示,比如第3题,不管是选中的选项,还是不选中的选项,都是对最终答案的一个约束,必须满足。
但是对于第7题,却可以用×表示(这一点需读者细细品味)
(2)单独看第8、9题
8,十个答案中,A和E共有几个
A2 B3 C4 D5 E6
9,十个答案中,B和C和D共有几个
A某个质数 B某个阶乘数 C平方数 D立方数 E5的倍数
如果8选A,那么10-2=8是立方数,那么9选D
BCE同理
如果8选D,那么10-5=5是质数也是5的倍数,那么9无法选
所以这2个题目可以等价代替为
8,十个答案中,A和E共有几个
A2 B3 C4 D× E6
9,上题的答案是
A B B C C E D A E ×
(3)再看第7、8、9题
7,下题答案是
A × B × C A D C E ×
8,十个答案中,A和E共有几个
A2 B3 C4 D× E6
9,上题的答案是
A B B C C E D A E ×
这3题可以替换为
7,下题答案是
A × B × C A D C E ×
8,十个答案中,A和E共有几个
A2 B× C4 D× E×
9,上题的答案是
A × B C C × D A E ×
还可以继续下去,不过效果不明显了,我就不继续了。
如果一直继续下去,不需要编程,全部推出答案也是可以的。
3,编程求解
简化后的题目:
1,十个题中,第几题是第一个选了B的题
A2 B3 C4 D5 E6
2,十个题中,唯一的连续两个具有相同答案的题是
A第23题 B第34题 C第45题 D第56题 E第67题
3,本题和第几题答案相同
A1 B2 C4 D7 E6
4,十个题中,共有几个选A
A0 B1 C2 D3 E4
5,本题和第几题答案相同
A10 B9 C8 D7 E6
6,十个答案中,A的个数和哪个的个数相同
A B B C C D D E E以上都不是
7,下题答案是
A × B × C A D C E ×
8,十个答案中,A和E共有几个
A2 B× C4 D× E×
9,上题的答案是
A × B C C × D A E ×
10,本题的答案是
A A B B C C D D E E
代码:
#include<iostream>
using namespace std;
int list[11];
bool f1()
{
for (int i = 1; i <=6; i++)if (list[i] == 2)return i == list[1] + 1;
return false;
}
bool f2()
{
int temp = 0;
int sum = 0;
for (int i = 1; i <= 9; i++)
{
if (list[i] == list[i + 1])
{
temp = i;
sum++;
}
}
if (sum != 1)return false;
return temp == list[2] + 1;
}
int f3()
{
int temp[5] = { 1, 2, 4, 7, 6 };
for (int i = 0; i < 5; i++)
{
if (i+1 == list[3] && list[temp[i]] != list[3])return 0;
if (i+1 != list[3] && list[temp[i]] == list[3])return 0;
}
return 1;
}
int get(char c) //c是从A到E
{
int sum = 0;
for (int i = 1; i <= 10; i++)if (list[i] == c-'A'+1)sum++;
return sum;
}
bool f4()
{
return get('A') + 1 == list[4];
}
int f5()
{
int temp[5] = { 10, 9, 8, 7, 6 };
for (int i = 0; i < 5; i++)
{
if (i+1 == list[4] && list[temp[i]] != list[4])return 0;
if (i+1 != list[4] && list[temp[i]] == list[4])return 0;
}
return 1;
}
bool f6()
{
int sum = 0;
int temp = 0;
for (int i = 1; i < 5; i++)
{
if (get('A') == get('A' + i))
{
sum++;
temp = i;
}
}
if (sum == 0)return list[6] == 5;
if (sum == 1)return list[6] == temp;
return false;
}
bool f8()
{
if (list[8] == 1)return (get('A') + get('E') == 2);
if (list[8] == 3)return (get('A') + get('E') == 4);
return false;
}
void out()
{
for (int i = 1; i <= 10; i++)
{
char ch = 'A' + list[i]-1;
cout << ch;
}
cout << endl;
}
int main()
{
for (list[1] = 1; list[1] <= 5; list[1]++)
for (list[2] = 1; list[2] <= 5; list[2]++)
for (list[3] = 1; list[3] <= 5; list[3]++)
for (list[4] = 1; list[4] <= 5; list[4]++)
for (list[5] = 1; list[5] <= 5; list[5]++)
for (list[6] = 1; list[6] <= 5; list[6]++)
for (list[10] = 1; list[10] <= 5; list[10]++)
{
list[8] = 1; list[7] = 3; list[9] = 4;
if (f1() && f2() && f3() && f4() && f5() && f6() && f8())out();
list[8] = 3; list[7] = 4; list[9] = 2;
if (f1() && f2() && f3() && f4() && f5() && f6() && f8())out();
}
cout << "end";
system("pause>nul");
return 0;
}
运行结果:
CDEBEEDCBA
end
用状态压缩写法:
int main()
{
int s = pow(5, 6);
for (int x = 0; x < s; x++) {
int y = x;
for (int i = 6; i > 0; i--)list[i] = y % 5 + 1, y /= 5;
for (list[10] = 1; list[10] <= 5; list[10]++)
{
list[8] = 1; list[7] = 3; list[9] = 4;
if (f1() && f2() && f3() && f4() && f5() && f6() && f8())out();
list[8] = 3; list[7] = 4; list[9] = 2;
if (f1() && f2() && f3() && f4() && f5() && f6() && f8())out();
}
}
cout << "end";
system("pause>nul");
return 0;
}
如果不是单选题,而是多选题,直接用枚举法肯定是不行的。
七,10个关联的多选题
1,问题
每题最少可以选1个,最多可以选5个。
1,第_____题是单项选择题
A、5 B、4 C、3 D、2 E、1
2,第_____题答案是全选
A、10 B、9 C、8 D、7 E、6
3以下选项正确的是_____
A、总共有4题单选题
B、第5题不是单选题
C、有连续2题答案相同的题目
D、所有题中有3题答案相同
E、答案当中有选B的题目总共有4题
4这题答案跟前几题答案不同,本题的答案是_____
A、A B、B C、C D、D E、E
5、在答案中出现得最多的选项是_____
A、A B、B C、C D、D E、E
6,这题答案比下一题答案多选一个,这题_____
A、选A的话一定要选B
B、选B的话一定要选C
C、选C的话一定要选A
D、选E的话一定要选D
E、选D的话一定要选E
7,有选E的题目是第_____ 题
A、2 B、4 C、6 D、8 E、10
8,没有选C的题目是第_____ 题
A、1 B、3 C、5 D、7 E、9
9,答案只有元音字母(A和E)的题目是_____
A、10 B、8 C、6 D、4 E、2
10,答案只有辅音字母(BCD)的题目是_____
A、9 B、7 C、5 D、3 E、1
2,逻辑化简
(1)第4题一定是单选题,所以第1题选B
(“答案是AB”表示选AB且不选CDE,单纯说“选B”的话,ACDE选不选不确定)
所以,第1题不选E,ACD里面至少还需选1个。
(2)第6题推出,第7题不是全选,所以第2题不选D
(3)第6题选ABC,DE里面可以选一个,也可以都选
所以第9题不选C,第2题不选B,第8题选E,第7题选D。
(4)第10题不可能同时选B和E,所以第2题不选A
(5)如果第2题同时选C和E,那么根据第8题可知第7题不选C,但是根据第6题可知第7题选C,矛盾!
所以第2题答案要么就是C,要么就是E,是单选。所以第1题选D
(6)综上所述,题目可以化简为
1,第_____题是单项选择题
A、5 B、4√ C、3 D、2√ E、1×
2,第_____题答案是全选
A、10× B、9× C、8 D、7× E、6
3以下选项正确的是_____
A、总共有4题单选题
B、第5题不是单选题
C、有连续2题答案相同的题目
D、所有题中有3题答案相同
E、答案当中有选B的题目总共有4题
4这题答案跟前几题答案不同,本题的答案是_____
A、A B、B C、C D、D E、E
5、在答案中出现得最多的选项是_____
A、A B、B C、C D、D E、E
6,这题答案比下一题答案多选一个,这题_____
A√ B√ C√ D 选D E 选E
7,有选E的题目是第_____ 题
A、2 B、4 C、6 D、8√ E、10
8,没有选C的题目是第_____ 题
A、1 B、3 C、5 D、7 E、9√
9,答案只有元音字母(A和E)的题目是_____
A、10 B、8 C、6× D、4 E、2
10,答案只有辅音字母(BCD)的题目是_____
A、9 B、7 C、5 D、3 E、1
3,分类求解
基于上面的化简,继续推理。
(1)如果第2题选C不选E
则8全选,7不选A,4不选C,9不选E,则13579不选C,9不选B,则6不选E
若1选A,则10不选E,3不选B,则7不选E,则10选B......不断的推理下去,直到所有选项都确定了选或者不选的最后一刻,终于得出矛盾。
所以,1不选A。
则10选E,3选B,则7选E,则10不选B
接下来还需要继续分类
(1.1)如果10选A
则9选D不选A,3不选A,则4不选BD,
分析有3题相同的条件,发现只能是135的答案都是BD才可以满足,但是这样可以推出来B和D的数量并不一样,矛盾。
所以3不选D选E,所以57不选B,矛盾。
(1.2)如果10不选A
则9选A,则10不选CD,
分析有3题相同的条件,发现只能是135的答案都是BD或者是357的答案都是BDE才可以满足,
如果357的答案都是BDE,那么3就不选E,矛盾。
如果135的答案都是BD,那么9选D,但是这样可以推出来B和D的数量并不一样,矛盾。
所以3不选D
如果4选E,则4不选ABD,7选B,9选D,则3不选AE,矛盾。
所以4不选E
则7不选B,则6不选D
(1.2.1)如果3选A
则9不选D,则4不选A,
如果3选E,则45不选B,所以最终答案是
1 BD 2 C 3 ABE 4 D 5 ADE或AD或AE或DE 6 ABC 7 DE 8 ABCDE 9 A 10 E
如果3不选E,则5选B,则4选D,所以最终答案是
1 BD 2 C 3 AB 4 D 5 ABD或AB 6 ABC 7 DE 8 ABCDE 9 A 10 E
(1.2.2)如果3不选A
则3选E,9选D,则4选A,5不选B,所以最终答案是
1 BD 2 C 3 BE 4 A 5 ADE或AD或AE或DE 6 ABC 7 DE 8 ABCDE 9 A 10 E
(2)如果第2题选E不选C
则6全选,7选A,9选E,4不选E,则7不选B选ACDE,10不选AB,则8不选D,10选E,则1不选A,则3选B
(2.1)如果1选C
则3不选ACDE,8不选A,则8选B,10选D,则9不选B
根据3的条件可以推出,9和10都是多选,所以9不选A选D,所以4单选A
因为9和10答案不同所以10选C,所以5不选AE,分析一下各个选项的数量,矛盾。
(2.2)如果1不选C
则8选A,分析各选项数量,发现E至少有6个,所以5要选的选项至少要有7个,则5不选ABC,
则5选DE,则8选C
因为49不能同时选D,而D的总数要和E一样,所以3选D,10选D,则3不选AE,9不选A,
所以有3个题目的答案相同,则只能是5和9和10的答案都是DE,则4单选A,所以最终答案是
1 BD 2 E 3 BCD 4 A 5 DE 6 ABCDE 7 ACDE 8 ACE 9 DE 10 DE
(3)综上,答案有4组:
1 BD 2 C 3 ABE 4 D 5 ADE或AD或AE或DE 6 ABC 7 DE 8 ABCDE 9 A 10 E
1 BD 2 C 3 AB 4 D 5 ABD或AB 6 ABC 7 DE 8 ABCDE 9 A 10 E
1 BD 2 C 3 BE 4 A 5 ADE或AD或AE或DE 6 ABC 7 DE 8 ABCDE 9 A 10 E
1 BD 2 E 3 BCD 4 A 5 DE 6 ABCDE 7 ACDE 8 ACE 9 DE 10 DE
4,编程求解
用了很多状态压缩来进行枚举,需要注意每个题目至少选1个选项。
第9题没有用枚举,每个选项都是计算出来的,更是需要注意每个题目至少选1个选项。
代码:
#include<iostream>
using namespace std;
int list[11][6];
void f1(); void f2(); void f3(); void f4(); void f5();
void f6(); void f7(); void f8(); void f9(); void f10();
char a = 'A';
void f1()
{
list[1][2] = 1; list[1][4] = 1; list[1][5] = 0;
for (int i = 0; i < 4; i++)
{
list[1][1] = i / 2; list[1][3] = i % 2;
f2();
}
}
void f2()
{
for (int i = 0; i < 6; i++)list[2][i] = 0;
list[2][3] = 1;
f3();
list[2][3] = 0;
list[2][5] = 1; //1D
f3();
}
int getSum(int i) //第i题选了几个
{
return list[i][1] + list[i][2] + list[i][3] + list[i][4] + list[i][5];
}
void f3()
{
for (int i = 1; i < 32; i++)
{
list[3][1] = i / 16 % 2;
list[3][2] = i / 8 % 2;
list[3][3] = i / 4 % 2;
list[3][4] = i / 2 % 2;
list[3][5] = i % 2;
if (list[1][1] == list[3][2])continue; //3B
int sum = getSum(3);
if (list[1][3])
{
if (sum - 1)continue;
}
else if (sum == 1)continue; //1C
f4();
}
}
void f4()
{
for (int i = 1; i <= 5; i++)
{
if (list[2][i] || list[1][3] && list[3][i])continue;
for (int j = 1; j < 6; j++)list[4][j] = (i == j); //4、1B
f5();
}
}
void f5()
{
for (int i = 1; i < 32; i++)
{
list[5][1] = i / 16 % 2;
list[5][2] = i / 8 % 2;
list[5][3] = i / 4 % 2;
list[5][4] = i / 2 % 2;
list[5][5] = i % 2;
int sum = getSum(5);
if (list[1][1])
{
if (sum - 1)continue;
}
else if (sum == 1)continue; //1A、1
f6();
}
}
void f6()
{
list[6][1] = list[6][2] = list[6][3] = 1;
for (int i = 0; i < 4; i++)
{
list[6][4] = i / 2; list[6][5] = i % 2;
int sum = getSum(6);
if (list[2][5])
{
if (sum - 5)continue;
}
else if (sum == 5)continue; //2E
f7();
}
}
void f7()
{
int sum = getSum(6) - 1;
list[7][1] = list[2][5]; //7A
list[7][2] = list[4][5]; //7B
list[7][3] = list[6][5]; //7C
list[7][4] = 1;
list[7][5] = 1;
if (getSum(7) == sum)f8(); //6
list[7][5] = 0;
if (getSum(7) == sum)f8();
}
void f8()
{
list[8][1] = 1 - list[1][3]; //8A
list[8][2] = 1 - list[3][3]; //8B
list[8][3] = 1 - list[5][3]; //8C
list[8][4] = 1 - list[7][3]; //8D
list[8][5] = 1; //8E、8
int sum = getSum(8);
if (list[2][3])
{
if (sum - 5)return;
}
else if (sum == 5)return; //2C、2
f9();
}
int getBCD(int i) //第i题选BCD的数量
{
return list[i][2] + list[i][3] + list[i][4];
}
void f9()
{
list[9][2] = getBCD(8) == 0; //9B
list[9][3] = 0;
list[9][4] = getBCD(4) == 0; //9D
list[9][5] = getBCD(2) == 0; //9E
list[9][1] = 1;
if(getSum(9))f10();
list[9][1] = 0;
if (getSum(9))f10();
}
int getAE(int i) //第i题选AE的数量
{
return list[i][1] + list[i][5];
}
void f10()
{
list[10][1] = getAE(9) == 0;
list[10][2] = getAE(7) == 0;
list[10][3] = getAE(5) == 0;
list[10][4] = getAE(3) == 0;
list[10][5] = getAE(1) == 0; //10
if (getSum(10) == 0)return;
if (list[9][1] != (getBCD(10) == 0))return; //9A、9
if (list[7][5] != list[10][5])return; //7E、7
int sum = 0;
for (int i = 1; i <= 10; i++)sum += getSum(i) == 1;
if (list[3][1] != (sum == 4))return; //3A
sum = 0;
for (int i = 1; i < 10; i++)
if (list[i][1] == list[i + 1][1] && list[i][2] == list[i + 1][2] && list[i][3] == list[i + 1][3] && list[i][4] == list[i + 1][4] && list[i][5] == list[i + 1][5])sum++;
if (list[3][3] != (sum>0))return; //3C
sum = 0;
for (int i = 1; i <= 10; i++)sum += list[i][2];
if (list[3][5] != (sum == 4))return; //3E
int max;
for (int i = 1; i <= 5; i++)
{
if (list[5][i] == 0)continue;
sum = 0;
for (int j = 1; j <= 10; j++)sum += list[j][i];
max = sum;
break;
}
for (int i = 1; i <= 5; i++)
{
sum = 0;
for (int j = 1; j <= 10; j++)sum += list[j][i];
if (list[5][i])
{
if (max != sum)return;
}
else if (max <= sum)return; //5
}
for (int i = 1; i <= 10; i++)
{
for (int j = 1; j <= 5; j++)
{
if (list[i][j])
{
char ch = a + j - 1;
cout << ch;
}
}
cout << " ";
}
cout << endl;
}
int main()
{
f1();
cout << "end";
system("pause>nul");
return 0;
}
输出的答案,还不是最后的答案,还需要手动完成最后一步验证。
第3题的D选项:所有题中有3题答案相同
这个条件,编程起来比较繁琐,而且效率比较低下,所以我没有写验证代码。
上述代码运行1秒即可结束
验证第3题的D选项可以发现,很巧的是,上面11行刚好是11组正确答案,下面3组是验证可以排除的。
八,第十道推理题
这是一个游戏,感觉名字起的很烂,直接叫十道推理题都比这好。
开发者就是根据上面的十个关联的单选题来的灵感,用程序随机生成N个关联的单选题,N=1,2,3......
因为是随机的,所有每一关每次玩都不一样。
(1)关卡1
(2)关卡2
(3)关卡3
(4)关卡4
(5)关卡5
答案是BDCAC
做题的时候为了方便,把相近的题目放到一起了,所以顺序乱了,下同。
(6)关卡6
(7)关卡7
(8)关卡8
滚动截屏太长的话有点问题,所以我分开截了。
(9)关卡9
错别字领其实是邻。
第8题说哪两道题,其实是哪一道题,下同。
这一关出现了新的描述,哪两题满足×××条件,只要选项中有一题不满足,那这个选项就是错的。
(10)关卡10
九,十条陈述
1,题目
2,分析
一般的n个判断题,我们要做的就是根据这n个条件推导出这n个变量的值。
这里因为加入了未知数x,所以我们要根据这10个条件推导出这11个变量的值。
3,标准模型
11个变量分别是:整数x和10个原子谓词公式ABCDEFGHJK
组成新的谓词公式:
(1)M = J | K,其中|是或运算
(2)N = (!A & B) | (A & !B)
(3)O 表示 序列【ABCDEFGHJK】中有3个连续的false
(4)P 表示 序列【ABCDEFGHJK】中第一个和最后一个true的下标之差是x的约数。下标指的就是从1到10的下标,下同。
(5)Q 表示 序列【ABCDEFGHJK】中为true的下标之和等于x
(6)R 表示 !(F & !G & !H & !J & !K)
(7)S 表示 序列【ABCDEFGHJK】中为true的每个下标都是x的约数。
(8)T 表示 x=序列【ABCDEFGHJK】中为true的数量再乘以10
(9)U 表示 x的约数总数(不算1和x这2个平凡约数)大于 序列【ABCDEFGHJK】中为true的下标之和
(10)V 表示 序列【ABCDEFGHJK】中没有3个连续的true
10个条件分别是:
(1)M=A
(2)N=B
(3)O=C
(4)P=D
(5)Q=E
(6)R=F
(7)S=G
(8)T=H
(9)U=J
(10)V=K
4,推理的通用技巧
前面我们已经知道了指涉环的概念,通用技巧主要2条:
(1)优先分析短的指涉环,从而尽快获得确定信息
(2)优先分析出度大的节点,即语义更丰富的选项,从而尽快确定该选项是true还是false
5,推理
(推理1)
根据条件(2),(!A & B) | (A & !B)=B,所以A=false,且条件(2)已用完。
根据条件(6), !(F & !G & !H & !J & !K)=F,所以F=true,条件(6)化简成(!G & !H & !J & !K)=false,即(G|H|J|K)=true
此时完整的题目是:
有整数x和10个原子谓词公式ABCDEFGHJK,根据如下条件求出这11个变量
(1) J | K = A
(2)A=false,F=true
(3)O 表示 序列【ABCDEFGHJK】中有3个连续的false,O=C
(4)P 表示 序列【ABCDEFGHJK】中第一个和最后一个true的下标之差是x的约数,P=D
(5)Q 表示 序列【ABCDEFGHJK】中为true的下标之和等于x,Q=E
(6)(G|H|J|K)=true
(7)S 表示 序列【ABCDEFGHJK】中为true的每个下标都是x的约数,S=G
(8)T 表示 x=序列【ABCDEFGHJK】中为true的数量再乘以10,T=H
(9)U 表示 x的约数总数(不算1和x这2个平凡约数)大于 序列【ABCDEFGHJK】中为true的下标之和,U=J
(10)V 表示 序列【ABCDEFGHJK】中没有3个连续的true,V=K
(推理2)
根据条件(1)(2)可得,J=false, K=false,且条件(1)已用完。
所以(6)可以化简成(G|H)=true,(9)(10)也可以化简
此时完整的题目是:
有整数x和10个原子谓词公式ABCDEFGHJK,根据如下条件求出这11个变量
(1) J=false, K=false
(2)A=false,F=true
(3)O 表示 序列【ABCDEFGHJK】中有3个连续的false,O=C
(4)P 表示 序列【ABCDEFGHJK】中第一个和最后一个true的下标之差是x的约数,P=D
(5)Q 表示 序列【ABCDEFGHJK】中为true的下标之和等于x,Q=E
(6)(G|H)=true
(7)S 表示 序列【ABCDEFGHJK】中为true的每个下标都是x的约数,S=G
(8)T 表示 x=序列【ABCDEFGHJK】中为true的数量再乘以10,T=H
(9)x的约数总数(不算1和x这2个平凡约数)小于等于 序列【ABCDEFGHJK】中为true的下标之和
(10)序列【ABCDEFGHJK】中有3个连续的true
(推理3)
根据条件(1)(2),可以代入序列组成的谓词公式,
化简后的题目是:
有整数x和10个原子谓词公式ABCDEFGHJK,根据如下条件求出这11个变量
(1) J=false, K=false
(2)A=false,F=true
(3)O 表示 BC都是false,或CDE都是false,或H=false,O=C
(4)P 表示 序列【ABCDEFGHJK】中第一个和最后一个true的下标之差是x的约数,P=D
(5)Q 表示 序列【ABCDEFGHJK】中为true的下标之和等于x,Q=E
(6)(G|H)=true
(7)S 表示 序列【ABCDEFGHJK】中为true的每个下标都是x的约数,S=G
(8)T 表示 x=序列【BCDEFGH】中为true的数量再乘以10,T=H
(9)x的约数总数(不算1和x这2个平凡约数)小于等于 序列【ABCDEFGHJK】中为true的下标之和
(10)BCD都是true,或者DE都是true,或者EG都是true,或者GH都是true
(推理4)
根据条件(3)可得,B|C = true,C|D|E=true,C=!H,且条件(3)已用完。
我们用1表示true,0表示false,则化简后的题目是:
有整数x和10个原子谓词公式ABCDEFGHJK,根据如下条件求出这11个变量
(1) J=false, K=false
(2)A=false,F=true
(3)B|C = true,C|D|E=true,C=!H
(4)P 表示 (B)+(H)+4 是x的约数,P=D
(5)Q 表示 序列【ABCDEFGHJK】中为true的下标之和等于x,Q=E
(6)G|H=true
(7)S 表示 序列【ABCDEFGHJK】中为true的每个下标都是x的约数,S=G
(8)T 表示 x=序列【BCDEFGH】中为true的数量再乘以10,T=H
(9)x的约数总数(不算1和x这2个平凡约数)小于等于 序列【ABCDEFGHJK】中为true的下标之和
(10)BCD都是true,或者DE都是true,或者EG都是true,或者GH都是true
(推理5)
纯逻辑推理只能到此为止了,接下来比较用数论继续推了。
如果S=true,则x是42的倍数,则T=false,Q=false
所以S&T = false,S&Q=false,即G&H=false,G&E=false
所以条件(10)可以化简成“BCD都是true,或者DE都是true”,所以D=true。
化简后的题目是:
有整数x和10个原子谓词公式ABCDEFGHJK,根据如下条件求出这11个变量
(1) A=false,D=true, F=true,J=false, K=false
(2)G&H=false,G&E=false
(3)B|C = true,C=!H
(4) (B)+(H)+4 是x的约数
(5)Q 表示 序列【ABCDEFGHJK】中为true的下标之和等于x,Q=E
(6)G|H=true
(7)S 表示 序列【ABCDEFGHJK】中为true的每个下标都是x的约数,S=G
(8)T 表示 x=序列【BCDEFGH】中为true的数量再乘以10,T=H
(9)x的约数总数(不算1和x这2个平凡约数)小于等于 序列【ABCDEFGHJK】中为true的下标之和
(10) (B&C)|E = true
(推理6)
根据G&H=false G|H=true C=!H 可得,C=G
根据C=G G&E=false (B&C)|E = true B|C = true 可得B=true
化简后的题目是:
有整数x和10个原子谓词公式ABCDEFGHJK,根据如下条件求出这11个变量
(1) A=false,B=true,D=true, F=true,J=false, K=false
(2)G&E=false,C|E = true
(3)C=!H,C=G
(4) (H)+5 是x的约数
(5)Q 表示 序列【ABCDEFGHJK】中为true的下标之和等于x,Q=E
(6)S 表示 序列【ABCDEFGHJK】中为true的每个下标都是x的约数,S=G
(7)T 表示 序列【CEF】中为true的数量加3,再乘以10就等于x,T=H
(8)x的约数总数(不算1和x这2个平凡约数)小于等于 序列【ABCDEFGHJK】中为true的下标之和
(推理7)
根据条件(2)(3)可得,C=!E
化简后的题目是:
有整数x和10个原子谓词公式ABCDEFGHJK,根据如下条件求出这11个变量
(1) A=false,B=true,D=true, F=true,J=false, K=false
(2)C=!H,C=G, C=!E
(3) (H)+5 是x的约数
(4)Q 表示 序列【ABCDEFGHJK】中为true的下标之和等于x,Q=E
(5)S 表示 序列【ABCDEFGHJK】中为true的每个下标都是x的约数,S=G
(6)T 表示 序列【CEF】中为true的数量加3,再乘以10就等于x,T=H
(7)x的约数总数(不算1和x这2个平凡约数)小于等于 序列【ABCDEFGHJK】中为true的下标之和
(推理8)
很明显,只有2种情况,如果C=true,则:
- A=false,B=true,C=true, D=true, E=false, F=true,G=true,H=false, J=false, K=false
- 5 是x的约数
- 序列【ABCDEFGHJK】中为true的下标之和不等于x
- 序列【ABCDEFGHJK】中为true的每个下标都是x的约数
- 序列【CEF】中为true的数量加3,再乘以10不等于x
- x的约数总数(不算1和x这2个平凡约数)小于等于 序列【ABCDEFGHJK】中为true的下标之和
可以证明x是不存在的。
所以C=false,即:
- A=false,B=true,C=false, D=true, E=true, F=true,G=false,H=true, J=false, K=false
- 6 是x的约数
- 序列【ABCDEFGHJK】中为true的下标之和等于x
- 存在序列【ABCDEFGHJK】中为true的下标不是x的约数
- 序列【CEF】中为true的数量加3,再乘以10就等于x
- x的约数总数(不算1和x这2个平凡约数)小于等于 序列【ABCDEFGHJK】中为true的下标之和
可以证明x是不存在的。
额。。。。。是题目错了还是推理错了?
检查了一下,推理6化简题目写错了,
推理6得到的题目其实应该是:
有整数x和10个原子谓词公式ABCDEFGHJK,根据如下条件求出这11个变量
(1) A=false,B=true,D=true, F=true,J=false, K=false
(2)G&E=false,C|E = true
(3)C=!H,C=G
(4) (H)+5 是x的约数
(5)Q 表示 序列【ABCDEFGHJK】中为true的下标之和等于x,Q=E
(6)S 表示 序列【ABCDEFGHJK】中为true的每个下标都是x的约数,S=G
(7)T 表示 序列【CEGH】中为true的数量加3,再乘以10就等于x,T=H
(8)x的约数总数(不算1和x这2个平凡约数)小于等于 序列【ABCDEFGHJK】中为true的下标之和
(重新推理7)
根据(2)(3)可以推出E=!G
因为C!=H, E=!G,所以序列【CEGH】中为true的数量一定是2
化简后的题目是:
有整数x和10个原子谓词公式ABCDEFGHJK,根据如下条件求出这11个变量
(1) A=false,B=true,D=true, F=true,J=false, K=false
(2)C=!H,C=G,E=!G
(3) (H)+5 是x的约数
(4)Q 表示 序列【ABCDEFGHJK】中为true的下标之和等于x,Q=E
(5)S 表示 序列【ABCDEFGHJK】中为true的每个下标都是x的约数,S=G
(6)T 表示 x=50,T=H
(7)x的约数总数(不算1和x这2个平凡约数)小于等于 序列【ABCDEFGHJK】中为true的下标之和
(重新推理8)
结合(3)(6)可得,H=false,所以C=true,G=true,E=false
化简后的题目是:
根据如下条件求出x
(1) A=false,B=true,C=true,D=true, E=false,F=true,G=true,H=false,J=false, K=false
(2)5 是x的约数
(3)序列【ABCDEFGHJK】中为true的下标之和不等于x,即x!=22
(4)序列【ABCDEFGHJK】中为true的每个下标都是x的约数
(5)T 表示 x=50,T=false
(6)x的约数总数(不算1和x这2个平凡约数)小于等于22
接下来就是纯数论问题了,可以化简成x是420的倍数,且x的约数总数(不算1和x这2个平凡约数)小于等于22,所以x=420。