题目:汉语题,不用翻译了吧(⊙_⊙)。
度度熊最近很喜欢玩游戏。这一天他在纸上画了一个2行N列的长方形格子。他想把1到2N这些数依次放进去,但是为了使格子看起来优美,他想找到使每行每列都递增的方案。不过画了很久,他发现方案数实在是太多了。度度熊想知道,有多少种放数字的方法能满足上面的条件?
分析:组合,计数,卡塔兰数,数论。结果是卡塔兰数。
这里要计算第1000000个卡特兰数,这个数字十分巨大,第10000个就有几千位了。
题目本来是 Catalan(n+1)= Catalan(n)*(4*n+2)/(n+2)(mod M);
而我们无法计算除法的模,所以要全都保存,肯定TLE;
这里利用费马小定理转化下:
因为,b ^(M-1)= 1(mod M);
所以有 a / b mod M = a * b ^(M-1)/ b mod M = a * b ^ (M-1)mod M;
快速幂搞定。
说明:百度之星,错过了o(╯□╰)o(虽然赶上也不应定做出来什么╮(╯▽╰)╭)。
#include <iostream>
#include <cstdlib>
#include <cstdio>
using namespace std;
long long C[1000005] = {0LL};
long long spow(long long x, int n)
{
if (n == 1)
return x;
else {
long long v = spow(x, n/2);
if (n%2 == 0) return v*v%1000000007LL;
else return v*v%1000000007LL*x%1000000007LL;
}
}
int main()
{
C[1] = 1LL;
for (int i = 2 ; i < 1000001 ; ++ i) {
C[i] = C[i-1]*(4*i-2)%1000000007LL;
C[i] = C[i]*spow(i+1, 1000000005)%1000000007LL;
}
int n,m;
while (cin >> n)
for (int i = 1 ; i <= n ; ++ i) {
cin >> m;
cout << "Case #" << i << ":" << endl;
cout << C[m] << endl;
}
return 0;
}

度度熊在纸上画了一个2行N列的长方形,并尝试将1到2N的数字按照每行每列递增的方式排列。文章探讨了满足此条件的排列数量,并通过卡塔兰数公式进行计算。利用费马小定理简化计算过程,最终得到第1000000个卡塔兰数的值。

373

被折叠的 条评论
为什么被折叠?



