Penney's game (hdu 5169, zoj 3274)
2015-02-03 16:21
363 查看
Penney’s game (hdu 5169, zoj 3274)
matrix67有一篇介绍Penney’s game的文章,可以看下:
http://www.matrix67.com/blog/archives/6015
Penney’s game 概率的计算方法:
假如 a 和 b 是两个 n 位 01 串。如果 a 和 b 完全相等,那么记一个数字 1 ,如果不相等,那么记一个数字 0 。接下来,比较 a 的后面 n – 1 位以及 b 的前面 n – 1 位,如果相等,那么接着记一个数字 1 ,如果不相等,那么接着记一个数字 0 。接下来,比较 a 的后 n – 2 位以及 b 的前 n – 2 位,并根据比较结果记下数字 0 或者数字 1 。不断这样做下去,直到最后比较 a 的最后面 1 位和 b 的最前面 1 位,并产生新的数字。在整个过程中,你会依次记下
n 个数字,最终会得到一个 n 位的 01 串。把它当作一个二进制数,并转换成十进制。我们把最终的结果记为 L(a, b) 。举几个例子:
L(10110, 10110) = (10010)2 = 18
L(10110, 01011) = (00001)2 = 1
L(01011, 01011) = (10000)2 = 16
L(01011, 10110) = (01001)2 = 9
那么, 01 串 a 和 b 的胜率之比就是
(L(b, b) – L(b, a)) : (L(a, a) – L(a, b))
题目:
hdu 5169
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5169
题意:
小A和小B在玩一个游戏,他们一开始每人手上都有一个01字符串,其中记小A手上的为A串,小B手上的为B串。
现在有一枚均匀的硬币,以及一个空字符串S,游戏开始后每一回合都会投掷这枚硬币,如果正面向上,就在S后面添加一个字符'1',否则添加一个字符'0'。
一旦某一回合结束时A串成为了S的子串,小A就赢了,同样如果B串成为了S的子串,小B就赢了,有一个人获得胜利时游戏结束。为了避免两个人同时胜利的情况,保证A不为B的后缀,B也不为A的后缀。
在已知A和B的情况下,这个游戏是不是公平的呢,公平意味着小A与小B拥有相同的胜率,若不公平谁更有可能赢?
限制:
1 <= |A|,|B| <= 100
思路:
因为数据量小,只有100,利用Penney’s game的结论,可以直接用java大数暴力。
题目:
zoj 3274
题目链接:
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3274
题意:
这道题是上一道题的加强版,数据量较大。
限制:
1 <= |A|,|B| <= 100000
思路:
1. 首先要知道Penney’s game的结论:
2. 因为数据量比较大,要用kmp来优化。
kmp优化方式如下:
先算出模式串的next数组,不断地和母串的最后一位匹配,记录可以匹配的长度即可。
3. 用java大数会超时,要用c++模拟二进制大数减法。
matrix67有一篇介绍Penney’s game的文章,可以看下:
http://www.matrix67.com/blog/archives/6015
Penney’s game 概率的计算方法:
假如 a 和 b 是两个 n 位 01 串。如果 a 和 b 完全相等,那么记一个数字 1 ,如果不相等,那么记一个数字 0 。接下来,比较 a 的后面 n – 1 位以及 b 的前面 n – 1 位,如果相等,那么接着记一个数字 1 ,如果不相等,那么接着记一个数字 0 。接下来,比较 a 的后 n – 2 位以及 b 的前 n – 2 位,并根据比较结果记下数字 0 或者数字 1 。不断这样做下去,直到最后比较 a 的最后面 1 位和 b 的最前面 1 位,并产生新的数字。在整个过程中,你会依次记下
n 个数字,最终会得到一个 n 位的 01 串。把它当作一个二进制数,并转换成十进制。我们把最终的结果记为 L(a, b) 。举几个例子:
L(10110, 10110) = (10010)2 = 18
L(10110, 01011) = (00001)2 = 1
L(01011, 01011) = (10000)2 = 16
L(01011, 10110) = (01001)2 = 9
那么, 01 串 a 和 b 的胜率之比就是
(L(b, b) – L(b, a)) : (L(a, a) – L(a, b))
题目:
hdu 5169
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5169
题意:
小A和小B在玩一个游戏,他们一开始每人手上都有一个01字符串,其中记小A手上的为A串,小B手上的为B串。
现在有一枚均匀的硬币,以及一个空字符串S,游戏开始后每一回合都会投掷这枚硬币,如果正面向上,就在S后面添加一个字符'1',否则添加一个字符'0'。
一旦某一回合结束时A串成为了S的子串,小A就赢了,同样如果B串成为了S的子串,小B就赢了,有一个人获得胜利时游戏结束。为了避免两个人同时胜利的情况,保证A不为B的后缀,B也不为A的后缀。
在已知A和B的情况下,这个游戏是不是公平的呢,公平意味着小A与小B拥有相同的胜率,若不公平谁更有可能赢?
限制:
1 <= |A|,|B| <= 100
思路:
因为数据量小,只有100,利用Penney’s game的结论,可以直接用java大数暴力。
/*题意: 小A和小B在玩一个游戏,他们一开始每人手上都有一个01字符串,其中记小A手上的为A串,小B手上的为B串。 现在有一枚均匀的硬币,以及一个空字符串S,游戏开始后每一回合都会投掷这枚硬币,如果正面向上,就在S后面添加一个字符'1',否则添加一个字符'0'。 一旦某一回合结束时A串成为了S的子串,小A就赢了,同样如果B串成为了S的子串,小B就赢了,有一个人获得胜利时游戏结束。为了避免两个人同时胜利的情况,保证A不为B的后缀,B也不为A的后缀。 在已知A和B的情况下,这个游戏是不是公平的呢,公平意味着小A与小B拥有相同的胜率,若不公平谁更有可能赢? 限制: 1 <= |A|,|B| <= 100 思路: 1. 首先要知道Penney’s game的结论: 假如 a 和 b 是两个 n 位 01 串。如果 a 和 b 完全相等,那么记一个数字 1 ,如果不相等,那么记一个数字 0 。接下来,比较 a 的后面 n – 1 位以及 b 的前面 n – 1 位,如果相等,那么接着记一个数字 1 ,如果不相等,那么接着记一个数字 0 。接下来,比较 a 的后 n – 2 位以及 b 的前 n – 2 位,并根据比较结果记下数字 0 或者数字 1 。不断这样做下去,直到最后比较 a 的最后面 1 位和 b 的最前面 1 位,并产生新的数字。在整个过程中,你会依次记下 n 个数字,最终会得到一个 n 位的 01 串。把它当作一个二进制数,并转换成十进制。我们把最终的结果记为 L(a, b) 。举几个例子: L(10110, 10110) = (10010)2 = 18 L(10110, 01011) = (00001)2 = 1 L(01011, 01011) = (10000)2 = 16 L(01011, 10110) = (01001)2 = 9 那么, 01 串 a 和 b 的胜率之比就是 (L(b, b) – L(b, a)) : (L(a, a) – L(a, b)) 2. 因为数据量小,只有100,可以直接用java大数暴力。 */ import java.math.BigInteger; import java.util.Scanner; public class Main { static final int N = 105; static boolean cmp(char[] a, char[] b, int len) { if (len > b.length) return false; boolean ret = true; for (int i = 0; i < len; ++i) { if (b[i] != a[a.length - len + i]) { ret = false; break; } } return ret; } static BigInteger toBigInt(char a[], int len) { BigInteger ret = BigInteger.ZERO; for (int i = len - 1; i >= 0; --i) ret = ret.multiply(BigInteger.valueOf(2)).add(BigInteger.valueOf(a[i] - '0')); return ret; } public static void main(String[] args) { Scanner in = new Scanner(System.in); String str; char[] A = new char ; char[] B = new char ; char[] aa = new char , bb = new char , ab = new char , ba = new char ; BigInteger AA, BB, AB, BA; int ans; int T; T = in.nextInt(); while (T-- > 0) { str = in.next(); A = str.toCharArray(); str = in.next(); B = str.toCharArray(); for (int i = 0; i < A.length; ++i) { if (cmp(A, A, i + 1)) aa[i] = '1'; else aa[i] = '0'; if (cmp(A, B, i + 1)) ab[i] = '1'; else ab[i] = '0'; } for (int i = 0; i < B.length; ++i) { if (cmp(B, B, i + 1)) bb[i] = '1'; else bb[i] = '0'; if (cmp(B, A, i + 1)) ba[i] = '1'; else ba[i] = '0'; } AA = toBigInt(aa, A.length); BB = toBigInt(bb, B.length); AB = toBigInt(ab, A.length); BA = toBigInt(ba, B.length); //System.out.println(AA); //System.out.println(AB); //System.out.println(BB); //System.out.println(BA); ans = BB.subtract(BA).compareTo(AA.subtract(AB)); if (ans == 0) System.out.println("Fair"); else if (ans > 0) System.out.println("A"); else System.out.println("B"); } } } /* * 1 10110 01011 */
题目:
zoj 3274
题目链接:
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3274
题意:
这道题是上一道题的加强版,数据量较大。
限制:
1 <= |A|,|B| <= 100000
思路:
1. 首先要知道Penney’s game的结论:
2. 因为数据量比较大,要用kmp来优化。
kmp优化方式如下:
先算出模式串的next数组,不断地和母串的最后一位匹配,记录可以匹配的长度即可。
3. 用java大数会超时,要用c++模拟二进制大数减法。
/*题意: 小A和小B在玩一个游戏,他们一开始每人手上都有一个01字符串,其中记小A手上的为A串,小B手上的为B串。 现在有一枚均匀的硬币,以及一个空字符串S,游戏开始后每一回合都会投掷这枚硬币,如果正面向上,就在S后面添加一个字符'1',否则添加一个字符'0'。 一旦某一回合结束时A串成为了S的子串,小A就赢了,同样如果B串成为了S的子串,小B就赢了,有一个人获得胜利时游戏结束。为了避免两个人同时胜利的情况,保证A不为B的后缀,B也不为A的后缀。 在已知A和B的情况下,这个游戏是不是公平的呢,公平意味着小A与小B拥有相同的胜率,若不公平谁更有可能赢? 限制: 1 <= |A|,|B| <= 100000 思路: 1. 首先要知道Penney’s game的结论: 假如 a 和 b 是两个 n 位 01 串。如果 a 和 b 完全相等,那么记一个数字 1 ,如果不相等,那么记一个数字 0 。接下来,比较 a 的后面 n – 1 位以及 b 的前面 n – 1 位,如果相等,那么接着记一个数字 1 ,如果不相等,那么接着记一个数字 0 。接下来,比较 a 的后 n – 2 位以及 b 的前 n – 2 位,并根据比较结果记下数字 0 或者数字 1 。不断这样做下去,直到最后比较 a 的最后面 1 位和 b 的最前面 1 位,并产生新的数字。在整个过程中,你会依次记下 n 个数字,最终会得到一个 n 位的 01 串。把它当作一个二进制数,并转换成十进制。我们把最终的结果记为 L(a, b) 。举几个例子: L(10110, 10110) = (10010)2 = 18 L(10110, 01011) = (00001)2 = 1 L(01011, 01011) = (10000)2 = 16 L(01011, 10110) = (01001)2 = 9 那么, 01 串 a 和 b 的胜率之比就是 (L(b, b) – L(b, a)) : (L(a, a) – L(a, b)) 2. 因为数据量比较大,要用kmp来优化。 kmp优化方式如下: 先算出模式串的next数组,不断地和母串的最后一位匹配,记录可以匹配的长度即可。 3. 用java大数会超时,要用c++模拟二进制大数减法。 */ #include<iostream> #include<cstdio> using namespace std; #define LL long long const int N = 100050; LL aa[N / 50], bb[N / 50], ab[N / 50], ba[N / 50]; int next ; void getNext(char T[], int len) { int i, j; i = 0; j = next[0] = -1; while (i < len) { if (j == -1 || T[i] == T[j]) next[++i] = ++j; else j = next[j]; } } void deal(char S[], char T[], int slen, int tlen, LL res[]) { for (int i = 0; i <= max(slen / 50, tlen / 50); ++i) res[i] = 0; int i = 0, j = 0; if (slen >= tlen) i += slen - tlen; else j += tlen - slen; getNext(T, tlen); while (i < slen) { if (j == -1 || S[i] == T[j]) { ++i; ++j; if (i == slen && j != 0) { int bl = (j - 1) / 50; int mv = (j - 1) % 50; res[bl] |= (1LL) << mv; --i; j = next[j - 1]; } } else j = next[j]; } } char A , B ; void print(LL a[], int len) { for (int i = len - 1; i >= 0; --i) { int bl = i / 50; int mv = i % 50; cout << ((a[bl] & (1LL << mv)) > 0) << ' '; } cout << endl; } void sub(LL a[], LL b[], int alen, int blen) { int lim = max(alen / 50, blen / 50); int c = 0; for (int i = 0; i <= lim; ++i) { LL tmp = a[i] - b[i] - c; if (tmp < 0) { c = 1, tmp += (1LL) << 50; } else c = 0; a[i] = tmp; } } int n, m; int cmp(LL a[], LL b[], int alen, int blen) { int lim = max(alen / 50, blen / 50); int ret = 0; for (int i = lim; i >= 0; --i) { if (a[i] > b[i]) { ret = 1; break; } if (a[i] < b[i]) { ret = -1; break; } } return ret; } void gao() { int fa, fb; sub(bb, ba, m, m); sub(aa, ab, n, n); int ans = cmp(bb, aa, m, n); if (ans == 0) puts("Equal"); else if (ans == 1) puts("Hamlet"); else puts("Laertes"); } int main() { while (scanf("%d%d", &n, &m) && (n || m)) { scanf("%s%s", A, B); deal(A, A, n, n, aa); deal(B, B, m, m, bb); deal(A, B, n, m, ab); deal(B, A, m, n, ba); //print(aa, n); //print(ab, n); //print(bb, m); //print(ba, m); gao(); } return 0; }
相关文章推荐
- hdu1525-------Euclid's Game 找规律
- ZOJ 3644 Kitty's Game(DP)
- hdu 1525 Euclid's Game 博弈
- hdu 2147 kiki's game (打表找规律奇偶性规律)棋盘沿固定方向向没有经过的方格走, 直到不能走
- hdu_2147_kiki's game
- hdu 2147 kiki's game(基础博弈)
- HDU 2147 kiki's game 解题报告
- TOJ 4373 HDU 4430 ZOJ 3665 Yukari's Birthday / 二分
- hdu 1525 Euclid's Game
- [简单博弈] hdu 1525 Euclid's Game
- HDU 3544 Alice's Game
- hdu 2147 kiki's game
- hdu 1525 Euclid's Game
- ZOJ 1108 FatMouse's Speed (HDU 1160) DP
- zoj 1913 Euclid's Game
- ZOJ 3644 Kitty's Game
- hdu1525 Euclid's Game 找规律
- HDU 2147 kiki's game
- HDU-2147 kiki's game 简单博弈(*)
- hdu 1160 || zoj 1108 FatMouse's Speed