NOIP提高组—— 问题求解 与 完善程序
问题求解1:
甲乙丙丁四人在考虑周末要不要外出郊游。
已知①如果周末下雨,并且乙不去,则甲一定不去;②如果乙去,则丁一定去;③如果丙去,则丁一定不去;④如果丁不去,而且甲不去,则丙一定不去。如果周末丙去了,则甲___去了___(去了/没去)(1 分),乙___没去___(去
了/没去)(1 分),丁____没去__(去了/没去)(1 分),周末___没下雨___(下雨/没下雨)(2 分)。
分析:大水题,送分。只要别写错字就好了。
证明:
丙去了,联系③,丁不会去,一分 get
丁没去,联系②,乙不会去,一分 get
丁没去,丙去了,联系④,甲会去,一分 get
乙不去,甲去了,联系①,不会下雨,一分 get
问题求解2:
方程 a*b = (a or b) * (a and b),在 a,b 都取 [0, 31] 中的整数时,共有 454 组解。(* 表示乘法;or 表示按位或运算;and 表示按位与运算)
分析:考场上蒙了蒙,感觉等式成立的条件应该是 a 是 b 二进制下的子集或者 b 是 a 的子集。 然鹅并没有证明出来,于是就组合数搞了一下 A 掉了
(我同桌其实也 A 掉了,而且他还证出来了只不过他算错了2333)。
于是先证明一下:
不妨设 t = a- (a & b) 。(一开始我是设 t = a&b 的,所以死活证不出来), 于是 (x | y) = (y+t)
然后我们将 t 带入式子,得到: $a * b = ( a – t ) * ( b + t )$ 。
然后展开
=> $a * b = a*b + a*t – b*t – t*t$
=> $a*t – b*t – t*t = 0$
=> $t * (a – b – t) = 0$
=> 1. t=0 ; 2. a=b+t
考虑 t=0 的情况,t 等于零 意味着 a = a&b ,那么也就说明二进制下的 a 被包含于 b 中。
再考虑 a=b+t 的情况,这意味着 b=a&b,那么也就说明二进制下的 b 被包含于 a 中。
于是我们得出结论: 若原式成立,则在二进制下,a 是 b 的子集,或者 b 是 a 的子集。
然后我们考虑到如果 a=b ,那么原式必然成立,所以我们先将答案加上 32 (0~31每个数都与自己匹配),然后我们去讨论 b 是 a 的 真 子集情况,然后把讨论出来的答案 * 2 累加上去就好了。
那么我们先考虑 a 的数值。如果说这时候我们枚举 32 次,答案也是能出来的,但是这样做不仅低效率而且容易出错,那么我们考虑在用二进制的方法枚举 a 。
其实既然说了 b 是 a 的二进制真子集了,那么其实 我们只需要枚举在 log32 位空格(也就是 5 个空格)里面,放 k(k=0~5) 个 1 的方案就好了,因为这些数对答案的贡献是相同的,都是 k 个 1 里面计算真子集数。
那么方案数也就是组合数 C(5,k) 了。然后我们考虑在这 k 个位置里面安排 b 。 那么 b 的数值方案数也还是组合数,就是 $sigma_{s=1}^{k} C(k,s)$ 了。
然后我们将 $sigma_{s=1}^{k} C(k,s)$ 乘上 C(5,k),再乘以二,累加进答案就好了。
最近我听说这道题是吉老师出的啊?而且原数据范围是 [ 0~1023 ] 啊?不过后来谁验题后改成 [ 0~32 ] 了? 反正不是杜雨皓【逃】
于是我们得出结论:吉老师是铁了心要给 zjoi 选手盖上棺材板了 (但愿复赛…咳咳)
emmm…其实1024的范围用上面的方法是可以做初步的运算的(唔,别打脸),只不过应该是要用到更高深的组合数学理论了吧?(反正我不会,组合数没好好学哈~)
完善程序1:
对于一个1到