[HNOI2009]有趣的数列(卡塔兰数,线性筛)
[HNOI2009]有趣的数列
题目描述
我们称一个长度为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的值。
输入输出格式
输入格式:
输入文件只包含用空格隔开的两个整数n和P。输入数据保证,50%的数据满足n<=1000,100%的数据满足n<=1000000且P<=1000000000。
输出格式:
仅含一个整数,表示不同的长度为2n的有趣的数列个数mod P的值。
输入输出样例
输入样例#1:
3 10
输出样例#1:
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分代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#define lll long long
using namespace std;
lll read()
{
lll x=0,w=1;char ch=getchar();
while(ch>'9'||ch<'0') {if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*w;
}
lll n,p,ans;
lll dp[1000010];
lll f[2010][2010];
lll dfs(lll qian,lll zhi)
{
if(zhi==0) return 1;
if(f[qian][zhi]!=-1) return f[qian][zhi];
if(qian==0||qian==zhi)
{
f[qian][zhi]=dfs(zhi,zhi-1)%p;
return f[qian][zhi];
}
else
{
f[qian][zhi]=(dfs(qian,zhi-1)%p+dfs(qian-1,zhi)%p)%p;
return f[qian][zhi];
}
}
int main()
{
memset(f,-1,sizeof(f));
n=read();p=read();
dp[1]=1;
if(n<=2000) cout<<dfs(0,n)%p;
else
{
for(lll i=2;i<=n;i++)
{
dp[i]=(dp[i-1]*((4*i)%p-2)/(i+1))%p;
}
cout<<dp[n]%p;
}
return 0;
}
这道题的难点在于如何取模,由卡塔兰数必然是整数的性质,我们筛出数据范围内所有的质数,对于每一个和数,记录和数是由哪个质数筛出来的。将分子分母相同的质数数量直接减去,由性质,我们可以知道减出来的个数一定>=0。最后我们直接用快速幂求和即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#define lll long long
using namespace std;
lll read()
{
lll x=0,w=1;char ch=getchar();
while(ch>'9'||ch<'0') {if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*w;
}
lll n,p,ans;
lll pre[2000010];
lll num[2000010];
lll nop[2000010];
lll prime[500010];
lll quick_pow(lll x,lll k)
{
ans=1;
while(k)
{
if(k&1) ans=ans*x%p;
x=x*x%p;
k/=2;
}
return ans%p;
}
int main()
{
lll m=0;
n=read();p=read();
nop[1]=1;
for(lll i=2;i<=2*n;i++)
{
if(!nop[i]) {prime[++m]=i;pre[i]=i;}
for(lll j=1;j<=m,i*prime[j]<=2*n;j++)
{
nop[i*prime[j]]=1;pre[i*prime[j]]=prime[j];
if(i%prime[j]==0) break;
}
}
for(lll i=2;i<=n;i++)
{
lll ii=i;
while(ii!=1)
num[pre[ii]]--,ii/=pre[ii];
}
for(lll i=n+2;i<=2*n;i++)
{
lll ii=i;
while(ii!=1)
num[pre[ii]]++,ii/=pre[ii];
}
lll sum=1;
for(lll i=1;i<=m;i++)
{
if(num[prime[i]])
sum=(sum*quick_pow(prime[i],num[prime[i]]))%p;
}
cout<<sum%p;
}
[HNOI2009]有趣的数列(卡塔兰数,线性筛)的更多相关文章
- BZOJ_1485_[HNOI2009]有趣的数列_卡特兰数
BZOJ_1485_[HNOI2009]有趣的数列_卡特兰数 Description 我们称一个长度为2n的数列是有趣的,当且仅当该数列满足以下三个条件: (1)它是从1到2n共2n个整数的一个排列{ ...
- 洛谷P3200 [HNOI2009]有趣的数列(Catalan数)
P3200 [HNOI2009]有趣的数列 题目描述 我们称一个长度为2n的数列是有趣的,当且仅当该数列满足以下三个条件: (1)它是从1到2n共2n个整数的一个排列{ai}: (2)所有的奇数项满足 ...
- [bzoj1485][HNOI2009]有趣的数列_卡特兰数_组合数
有趣的数列 bzoj-1485 HNOI-2009 题目大意:求所有1~2n的排列满足奇数项递增,偶数项递增.相邻奇数项大于偶数项的序列个数%P. 注释:$1\le n\le 10^6$,$1\le ...
- bzoj1485: [HNOI2009]有趣的数列(Catalan数)
一眼卡特兰数...写完才发现不对劲,样例怎么输出$0$...原来模数不一定是质数= =... 第一次见到模数不是质数的求组合数方法$(n,m\leq 10^7)$,记录一下... 先对于$1$~$n$ ...
- 【题解】洛谷P3200 [HNOI2009] 有趣的数列(卡特兰数+质因数分解)
洛谷P3200:https://www.luogu.org/problemnew/show/P3200 思路 这题明显是卡特兰数的题型咯 一看精度有点大 如果递推卡特兰数公式要到O(n2) 可以证明得 ...
- [luogu1485 HNOI2009] 有趣的数列 (组合数学 卡特兰数)
传送门 Solution 卡特兰数 排队问题的简单变化 答案为\(C_{2n}^n \pmod p\) 由于没有逆元,只好用分解质因数,易证可以整除 Code //By Menteur_Hxy #in ...
- [HNOI2009]有趣的数列 题解(卡特兰数)
[HNOI2009]有趣的数列 Description 我们称一个长度为2n的数列是有趣的,当且仅当该数列满足以下三个条件: (1)它是从1到2n共2n个整数的一个排列{ai}: (2)所有的奇数项满 ...
- BZOJ 1485: [HNOI2009]有趣的数列( catalan数 )
打个表找一下规律可以发现...就是卡特兰数...卡特兰数可以用组合数计算.对于这道题,ans(n) = C(n, 2n) / (n+1) , 分解质因数去算就可以了... -------------- ...
- BZOJ 1485: [HNOI2009]有趣的数列 [Catalan数 质因子分解]
1485: [HNOI2009]有趣的数列 Description 我们称一个长度为2n的数列是有趣的,当且仅当该数列满足以下三个条件: (1)它是从1到2n共2n个整数的一个排列{ai}: (2)所 ...
随机推荐
- 学习日记15-1布局页同时引用多个model
@model Tuple<model1,model2> mvc布局页同时引用多个model 使用m.Item1.xxx m.Item2.xxx
- hashcode native
hashcode Java中的hashCode方法就是根据一定的规则将与对象相关的信息(比如对象的存储地址,对象的字段等)映射成一个数值,这个数值称作为散列值. 在设计hashCode方法和equal ...
- <foreach></foreach>标签
当传入参数为数组或者集合时需要通过<foreach></foreach>标签进行遍历 1.首先在po类中定义一个集合或者数组 比如 private List<Intege ...
- Ffmpeg AAC 编码错误 Input contains (near) NaN/+-Inf
Ffmpeg AAC编码 如果传入参Frame的Sample Format 为 AV_SAMPLE_FMT_S16,会出现 错误提示 Input contains (near) NaN/+-Inf,需 ...
- (转)SQLite部署-无法加载 DLL“SQLite.Interop.dll”: 找不到指定的模块
本文转载自:http://www.cnblogs.com/muzhiye/p/4284070.html 近期刚使用SQLite,主要引用的是System.Data.SQLite.dll这个dll,在部 ...
- Django学习之视图
一.Django的View(视图) 1.一个简单的视图 3.CBV和FBV 4.给视图加装饰器 使用装饰器装饰FBV 使用装饰器装饰CBV 二.Request对象和Response对象 1.reque ...
- 【GIS数据处理】 利用空间关系建立线CAD数据和属性表关联
这两天遇到一个不太容易解决的问题. 某燃气公司想自己对自建管线进行测绘便于数字化管理,在接受了简单的RTK测量培训和Cass成图培训后,就自己着手开干. 最近数据整理的差不多了,就提交给我请我帮忙核查 ...
- Helvetic Coding Contest 2019 online mirror (teams allowed, unrated)
http://codeforces.com/contest/1184 A1 找一对整数,使x^x+2xy+x+1=r 变换成一个分式,保证整除 #include<iostream> #in ...
- 阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_04 IO字节流_12_练习_文件复制
谁用字节可以读取任何文件. 读取后再写入到D盘去.这就是一个文件的复制. 怎么由C盘到D盘.这里要借助流技术 需要创建两个流,一个读取一个写入 图片复制过来了. 看一下图片的字节数.whilte循环要 ...
- Dnsmasq 安装配置
Dnsmasq 官网 http://www.thekelleys.org.uk/dnsmasq/doc.html Unbuntu 安装 Dnsmasq 参见https://help.ubuntu.c ...