BZOJ 1485: [HNOI2009]有趣的数列( catalan数 )

打个表找一下规律可以发现...就是卡特兰数...卡特兰数可以用组合数计算。对于这道题,ans(n) = C(n, 2n) / (n+1) , 分解质因数去算就可以了...

----------------------------------------------------------------------------------

#include<cstdio>
#include<cstring>
#include<algorithm>
 
using namespace std;
 
typedef long long ll;
 
const int maxn = 2000009;
 
int N, MOD;
int p[maxn], d[maxn], cnt[maxn], pn = 0;
bool F[maxn];
 
void Init() {
memset(F, 0, sizeof F);
for(int i = 2; i < maxn; i++) {
if(!F[i])
d[i] = p[pn++] = i;
for(int j = 0; j < pn && i * p[j] < maxn; j++) {
d[i * p[j]] = p[j];
F[i * p[j]] = true;
if(i % p[j] == 0) break;
}
}
}
 
int Power(int x, int t) {
int ret = 1;
for(; t; t >>= 1, x = ll(x) * x % MOD)
if(t & 1) ret = ll(x) * ret % MOD;
return ret;
}
 
int main() {
Init();
scanf("%d%d", &N, &MOD);
for(int i = 2; i <= N; i++)
cnt[i] = -1;
for(int i = N + 2; i <= (N << 1); i++)
cnt[i] = 1;
int ans = 1;
for(int i = (N << 1); i > 1; i--) {
if(!F[i]) {
ans = ll(ans) * Power(i, cnt[i]) % MOD;
continue;
}
cnt[d[i]] += cnt[i];
cnt[i / d[i]] += cnt[i];
}
printf("%d\n", ans);
return 0;
}

----------------------------------------------------------------------------------

 

 

1485: [HNOI2009]有趣的数列

Time Limit: 10 Sec   Memory Limit: 64 MB
Submit: 927   Solved: 490
[ Submit][ Status][ Discuss]

Description

 我们称一个长度为2n的数列是有趣的,当且仅当该数列满足以下三个条件:

    (1)它是从1到2n共2n个整数的一个排列{ai};

    (2)所有的奇数项满足a1<a3<…<a2n-1,所有的偶数项满足a2<a4<…<a2n

    (3)任意相邻的两项a2i-1与a2i(1≤i≤n)满足奇数项小于偶数项,即:a2i-1<a2i

    现在的任务是:对于给定的n,请求出有多少个不同的长度为2n的有趣的数列。因为最后的答案可能很大,所以只要求输出答案 mod P的值。

Input

输入文件只包含用空格隔开的两个整数n和P。输入数据保证,50%的数据满足n≤1000,100%的数据满足n≤1000000且P≤1000000000。

Output

仅含一个整数,表示不同的长度为2n的有趣的数列个数mod P的值。

Sample Input

3 10

Sample Output

5


对应的5个有趣的数列分别为(1,2,3,4,5,6),(1,2,3,5,4,6),(1,3,2,4,5,6),(1,3,2,5,4,6),(1,4,2,5,3,6)。

HINT

Source

 

转载于:https://www.cnblogs.com/JSZX11556/p/5001712.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值