有趣的数列
// 有趣的数列.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
/*
http://ybt.ssoier.cn:8088/problem_show.php?pid=1661
https://loj.ac/p/10239
我们称一个长度为 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 的有趣的数列。因为最后的答案可能很大,所以只要求输出答案 modP 的值。
【输入】
只包含用空格隔开的两个整数 n 和 P。
【输出】
仅含一个整数,表示不同的长度为 2n 的有趣的数列个数 modP 的值。
【输入样例】
3 10
【输出样例】
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}。
数据范围与提示:
对于 50% 的数据,n≤1000,P≤106 ;
对于全部数据,1≤n≤106,2≤P≤109 。
*/
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
typedef long long LL;
const int N = 2000010;
int n, p;
int primes[N], cnt;
bool st[N];
void init(int n) {
for (int i = 2; i <= n; i++) {
if (!st[i]) primes[cnt++] = i;
for (int j = 0; primes[j]*i <= n; j++) {
st[i * primes[j]] = true;
if (i % primes[j] == 0) break;
}
}
}
int qmi(int a, int k) {
int res = 1;
while (k) {
if (k & 1) res = (LL)res * a % p;
a = (LL)a * a % p;
k >>= 1;
}
return res;
}
int get(int n, int p) {
int s = 0;
while (n) {
s += n / p;
n /= p;
}
return s;
}
int C(int a, int b) {
int res = 1;
for (int i = 0; i < cnt; i++) {
int prime = primes[i];
int s = get(a, prime) - get(b, prime) - get(a - b, prime);
res = (LL)res * qmi(prime, s) % p;
}
return res;
}
int main()
{
scanf("%d%d",&n,&p);
init(n * 2);
cout << (C(n * 2, n) - C(n * 2, n - 1) + p) % p << endl;
return 0;
}
作 者: itdef
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力

