版权声明:本文为博主原创文章,可随意转载 https://blog.csdn.net/weixin_38686780/article/details/83039139
[HDU3544] Alice’s Game
题意:
给n块巧克力,第i块是 ,Alice只能垂直切,切成 ,并且 ,Bob只能横切,只能切成 ,并且
分析:
语言表达能力有限
我们采取
表示
的矩形对Alice的可切割次数的贡献,负数代表对Bob的贡献,如果所有
,Alice必赢,
,Bob(必赢)
对于HP(i,j) 的计算我们有如下法则
1.
的矩形贡献为n-1
2.
的矩形贡献为-(m-1)
3.
的矩形对HP的贡献为零,因为如果你首先下手切,都会给对手更多的机会,如果你能赢,你不会切这个,如果你输,那么切了这个你还会输。
4. 对于
的矩阵来说与3的状况相同,对答案的贡献都是0,首先下手都会给对手更多的机会
5. 贡献为零的有什么规律呢,我们发现原来是它们是
&&
6.
的矩形对于Alice来说有贡献,我们每一次可以选择都切成
的矩形,这样不会给对手机会,自己还可以增加一次切的机会,Bob也不会傻到切这个矩形,这样会给Alice更多机会,所以
的矩形,Alice 可以切
次
这个时候可以总结一下规律:
- 我们每一次切,都会切成 的 两块, ,递归下去 ,直到 ,这怎么计算呢
- 我们知道 当且仅当 &&
- 那么就有
参考代码
初级
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL solve(LL x,LL y)
{
LL t = 1;
while(t*2 <= y)
t <<= 1;
return x/t;
}
int main()
{
int T,n;
scanf("%d",&T);
for(int kase = 1; kase <= T; ++kase)
{
scanf("%d",&n);
LL x,y;
LL sum=0;
for(int i=1; i<=n; i++)
{
scanf("%lld%lld",&x,&y);
if(x > y) sum += solve(x,y)-1;
else sum -= solve(y,x) -1;
}
printf("Case %d: ",kase);
if(sum > 0) puts("Alice");
else puts("Bob");
}
return 0;
}
简化
下面这个版本就是大家在其他博客上看到的答案了
就是不停的对两边除以2,其实原理和
相同
#include <cstdio>
typedef long long LL;
int main()
{
int T; scanf("%d", &T);
for(int kase = 1; kase <= T; kase++)
{
int n; scanf("%d", &n);
LL a = 0, b = 0;
while(n--)
{
int x, y;
scanf("%d%d", &x, &y);
while(x > 1 && y > 1) { x >>= 1; y >>= 1; }
if(y == 1) a += (LL)x - 1;
if(x == 1) b += (LL)y - 1;
}
printf("Case %d: %s\n", kase, a > b ? "Alice" : "Bob");
}
return 0;
}