WOJ-Problem 1011 - Finding Teammates

本题参考了解题索引,采用二分:

若知F(1).....F(n) 求F(n+1)

可以将n+1序列中最大的那个数抽调出来,先固定它的位置,然后采用二分法依次求解。

(暂且用n+1来表示最大的那个数) n+1一定在某一组的最后面,设它在的组是第x组(不包含<3的组),则前面的序列有3*x-1,后面有n+1-3*x,故有下列公式:

F(n+1) = F(3*x-1)*F(n+1-3*x)*C(n,3*x-1)

注意当(n+1)%3==2时,还需要加上F(n)


本题中还有一个需要注意的点:

1、数据大小为64位,所以采用了长整型:long long

2、计算C组合时,应简化计算,C(n,k)=n*..(n-k+1)/K! =C(n,n-k)


代码如下:

#include
#include
#define rep(i, n) for (long long  i = 1; i <= (n); ++i)



using namespace std;
long long  comb(long long  n, long long  k){
	long long  a=1, b=1,c=1;
	if (k > n - k)   k = n - k;
	rep(i, k)
		a *= n+1-i;
	rep(i, k)
		b *= i;
	return a/b;
}

long long  F(long long  n){
	if (n == 0)
		return 1;
	if (n >= 0 && n <= 3)
		return 1;
	long long  x = n/ 3;
	long long  ans = 0;
	
	rep(i, x)
		ans += F(3 * i - 1)*F(n - 3 * i)*comb(n - 1, 3 * i - 1);
	if (n % 3 == 2)
		ans += F(n - 1);
	return ans;
}

int main(){
	long long  nt;
	while (cin>>nt)
	{
		if (!nt)
			cout << 0 << endl;
		else
		{
			long long anst = F(nt);
			cout << anst << endl;
		}
	}
}



你可能感兴趣的:(算法)