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)。
解题方法:
http://www.cnblogs.com/beiyuoi/p/5962846.html
http://www.cnblogs.com/hapjin/p/5758083.html
///BZOJ 1485 #include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 2000005;
LL P, ans=1;
int n, cnt;
bool check[maxn];
int minp[maxn], pr[maxn], c[maxn];
void predeal(int N)
{
minp[1]=1;
for(int i=2; i<= N; i++){
if(!check[i]) pr[++cnt]=i, minp[i]=cnt;
for(int j=1; j<=cnt && pr[j]*i<=N; j++){
check[pr[j]*i]=1;
minp[pr[j]*i]=j;
if(i%pr[j]==0) break;
}
}
}
LL powmod(LL a, LL b){
LL res=1;
while(b){
if(b&1) res=res*a%P;
a=a*a%P;
b>>=1;
}
return res;
}
void add(int x, int v){
while(x>1){
c[minp[x]]+=v;
x/=pr[minp[x]];
}
}
int main()
{
scanf("%d%lld", &n,&P);
predeal(2*n);
for(int i=n+2; i<=2*n; i++) add(i, 1);
for(int i=1; i<=n; i++) add(i,-1);
for(int i=1; i<=cnt; i++) ans=ans*powmod(pr[i], c[i])%P;
printf("%lld\n", ans);
return 0;
}