HDU
来源:互联网 发布:linux date 北京时间 编辑:程序博客网 时间:2024/06/14 04:57
题意:
给出n堆物品,每堆物品都有若干件,现在A和B进行游戏,每人每轮操作一次,按照如下规则:
1. 任意选择一个堆,假设该堆有x个物品,从中选择k个,要保证0<k<x且0<(x^k)<k。
2. 再增加一个大小为x^k的堆,另外有一个技能,可以将这个大小为x^k的堆变成(2*k)^x的堆,但是这个技能每个人只有一次机会可以使用。
现在问两人轮流操作,都采取最优策略,最后不能操作的人输,问谁会赢。
思路:
好题。看了别人题解才会。
先不考虑技能,其实每轮的操作就是将一个大小为x的堆分成大小为k和(x^k)的堆,这里很关键的一点是要能发现分堆之前x中二进制1的个数与分堆之后k与(x^k)的二进制1个数和的奇偶性是相同的。这个结论可以这样想,考虑x的某一位p,分四种情况:
1. 如果x的第p位为1且k的第p位也为1,那么(x^k)的第p位就是0.
2. 如果x的第p位为1且k的第p位也为0,那么(x^k)的第p位就是1.
3. 如果x的第p位为0且k的第p位也为1,那么(x^k)的第p位就是1.
4. 如果x的第p位为0且k的第p位也为0,那么(x^k)的第p位就是0.
可以发现无论哪种情况,奇偶性都不会发生变化,这是本题的关键。
另外考虑游戏怎么终止,很显然当一个堆x的二进制1的个数只有1个的时候,就不能再分了,那么如果所有的堆都这样,游戏就终止了,关键看从开始到终止需要奇数步还是偶数步就能判断输赢。
假设这些堆最后会分成y个堆,那么一共就分了y-n次,每个堆大小的二进制1个数都是1,这样二进制1的总是就是y,而y和x二进制1的个数z已经证明奇偶性相同,所以y-n和z-n奇偶性就是相同的,所以我们只需要判断z-n的奇偶性,这题就解决了,非常巧妙。
代码:
#include <bits/stdc++.h>using namespace std;const int MAXN = 1005;int cal(int x) { int res = 0; while (x) { res += x % 2; x >>= 1; } return res;}int main() { int T, cs = 0; scanf("%d", &T); while (T--) { int n, x, cnt = 0; scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%d", &x); cnt += cal(x) - 1; } printf("Case %d: ", ++cs); if (cnt & 1) puts("Yes"); else puts("No"); } return 0;}
0 0
- hdu
- hdu
- HDU
- hdu ()
- hdu
- hdu
- HDU
- HDU
- hdu
- hdu
- HDU
- Hdu
- hdu
- hdu-
- hdu
- hdu
- hdu
- HDU
- Python 标准库 —— zipfile(读取 zip 文件)
- DG计算机视觉公司机试题
- jq实现鼠标放置名字上显示详细内容的气泡效果
- iOS开发:关于automaticallyAdjustsScrollViewInsets的使用和注意事项
- python 中 字符串的应用
- HDU
- at 17:00 Shutdown -s -t 60
- 深入理解拉格朗日乘子法(Lagrange Multiplier) 和KKT条件
- Controlled-Channel Attacks: Deterministic Side Channels for Untrusted Operating Systems
- PHP实现http与https转化
- springmvc返回路径错误的问题
- ESB和SOAP的概念
- iOS中的RunLoop
- android ffmpeg neno优化