*[hackerrank]Volleyball Match

https://www.hackerrank.com/contests/w1/challenges/volleyball-match

此题不错,首先可以看出是DP,S(x, y)= S(x - 1, y) + S(x, y - 1)。然后比赛结束状态需要认真判断。三来,最后数据量很大(接近10^9)远超一般DP的数据量,分配数组都不行,里面是有规律的。下面是大数据失败的代码:

#include <vector>
#include <iostream>
#include <cstdlib>
#include <cmath>
using namespace std;

vector<vector<int> > ma;
int MOD = 1000000007;

bool validEnd(int a, int b) {
	// a >= b
	if (a < 25)
		return false;
	if (a == 25) {
		return ((a - b) >= 2);
	}
	else {
		return ((a - b) == 2);
	}
}

bool valid(int a, int b) {
	// a >= b
	if (a < 0 || b < 0)
		return false;
	if (a <= 25 && b <= 25)
		return true;
	else
		return ((a - b) <= 2);
}

int getCount(int a, int b, bool first) {
	if (!valid(a, b)) {
		return 0;
	}
    if (!first && validEnd(a, b)) {
        return 0;
    }
	if (ma[a][b] != -1) {
		return ma[a][b];
	}
	ma[a][b] = (getCount(a - 1, b, false) + getCount(a, b - 1, false)) % MOD;
	return ma[a][b];
}

int main() {
	int a, b;
	cin >> a >> b;
	if (a < b)
		swap(a, b);
	if (!validEnd(a, b)) {
		cout << 0 << endl;
		return 0;
	}
	ma.resize(a + 1);
	for (int i = 0; i < ma.size(); i++) {
		ma[i].resize(b + 1, -1);
	}
	ma[0][0] = 1;
	int r = getCount(a, b, true);
	cout << r << endl;
}

正确做法是观察到,大于25的比赛结束状态都是由24:24经由一个一个平局过来的,没经过一次增加一倍。这样只要改写main函数基本就行了,主要pow由于次数太高,会远超long的值域,需要改写每次都MOD一下。

int pw(int k) {
	if (k == 0)
		return 1;
	if (k == 1)
		return 2;
	int q = pw(k / 2);
	q = (1LL * q * q) % MOD;
	if (k % 2 == 1)
		return (q + q) % MOD;
	else
		return q;
}

int main() {
	int a, b;
	cin >> a >> b;
	if (a < b)
		swap(a, b);
	if (!validEnd(a, b)) {
		cout << 0 << endl;
		return 0;
	}
	ma.resize(26);
	for (int i = 0; i < ma.size(); i++) {
		ma[i].resize(26, -1);
	}
	ma[0][0] = 1;
	int r = 0;
	if (a == 25) {
		r = getCount(a, b, true);
	}
	else {
		r = getCount(24, 24, true);
		r = ((int64_t) r * pw(b - 24)) % MOD;
	}
	cout << r << endl;
}

  

posted @ 2014-08-16 22:21  阿牧遥  阅读(590)  评论(0编辑  收藏  举报