【BZOJ 3907】网格(Catalan数)
题目链接
这个题推导公式跟\(Catalan\)数是一样的,可得解为\(C_{n+m}^n-C_{n+m}^{n+1}\)
然后套组合数公式\(C_n^m=\frac{n!}{m!(n-m)!}\)
用阶乘分解的方法对分子和分母分解质因数然后指数相减,最后把剩下的高精度乘起来就行了,这样就避免了高精除法。可以用快速幂,但我太lan了,就直接暴力乘起来了。
说一下怎么阶乘分解,直接对每个数分解质因数的时间复杂度是\(O(n\sqrt{n})\),这显然是不可忍受的。
于是,考虑先用线筛求出\(1~n\)之间所有质数,然后枚举所有质数\(p\),\(1~n\)中所有\(p\)的倍数包含一个质因子\(p\),所有\(p^2\)的倍数包含一个质因子\(p\),...
所以,\(n!\)中\(p\)的指数为\(\sum_{i=1}^{\left\lfloor \log_p n\right\rfloor}\left\lfloor n/p^i \right\rfloor\)
枚举\(p\)求就行了,时间复杂度\(O(n\ log\ n)\)。
Code:
#include <cstdio>
#include <cstring>
const int MAXN = 10010;
int prime[MAXN], v[MAXN], c[MAXN], d[MAXN];
int n, cnt, m;
const int MOD = 10000;
struct Int{
int s[MAXN];
Int(int x){ memset(s, 0, sizeof s); s[++s[0]] = x % 10, x /= 10; }
void mul(int x){
s[1] *= x;
for(int i = 2; i <= s[0]; ++i){
s[i] = s[i] * x + s[i - 1] / MOD;
s[i - 1] %= MOD;
}
while(s[s[0]] >= MOD){
s[++s[0]] = s[s[0] - 1] / MOD;
s[s[0] - 1] %= MOD;
}
}
void cut(Int x){
for(int i = 1; i <= x.s[0]; ++i)
s[i] -= x.s[i];
for(int i = 1; i <= x.s[0]; ++i){
if(s[i] < 0){
s[i] += MOD;
--s[i + 1];
}
}
if(!s[s[0]]) --s[0];
}
void print(){
printf("%d", s[s[0]]);
for(int i = s[0] - 1; i; --i)
printf("%04d", s[i]);
}
}a(1), b(1);
int main(){
scanf("%d%d", &n, &m);
for(int i = 2; i <= n + m; ++i){
if(!v[i]){
v[i] = i;
prime[++cnt] = i;
}
for(int j = 1; j <= cnt; ++j){
if(prime[j] > v[i] || prime[j] * i > n + m) break;
v[prime[j] * i] = prime[j];
}
}
for(int i = 1; i <= cnt; ++i)
for(int j = prime[i]; j <= n + m; j *= prime[i])
c[i] += (n + m) / j;
for(int i = 1; i <= cnt && prime[i] <= n; ++i)
for(int j = prime[i]; j <= n; j *= prime[i])
c[i] -= n / j;
for(int i = 1; i <= cnt && prime[i] <= m; ++i)
for(int j = prime[i]; j <= m; j *= prime[i])
c[i] -= m / j;
for(int i = 1; i <= cnt; ++i)
for(int j = 1; j <= c[i]; ++j)
a.mul(prime[i]);
for(int i = 1; i <= cnt; ++i)
for(int j = prime[i]; j <= n + m; j *= prime[i])
d[i] += (n + m) / j;
for(int i = 1; i <= cnt && prime[i] <= n + 1; ++i)
for(int j = prime[i]; j <= n + 1; j *= prime[i])
d[i] -= (n + 1) / j;
for(int i = 1; i <= cnt && prime[i] <= m - 1; ++i)
for(int j = prime[i]; j <= m - 1; j *= prime[i])
d[i] -= (m - 1) / j;
for(int i = 1; i <= cnt; ++i)
for(int j = 1; j <= d[i]; ++j)
b.mul(prime[i]);
a.cut(b);
a.print();
return 0;
}
【BZOJ 3907】网格(Catalan数)的更多相关文章
- BZOJ 3907: 网格 [Catalan数 高精度]
3907: 网格 Time Limit: 1 Sec Memory Limit: 256 MBSubmit: 402 Solved: 180[Submit][Status][Discuss] De ...
- BZOJ 3907: 网格
Description 求不跨过直线 \(y=x\) ,到达 \((n,m)\) 的方案数. Sol 组合数学+高精度. 这个推导过程跟 \(Catalan\) 数是一样的. 答案就是 \(C^{n+ ...
- bzoj 3907: 网格 组合数学
3907: 网格 Time Limit: 1 Sec Memory Limit: 256 MBSubmit: 13 Solved: 7[Submit][Status][Discuss] Descr ...
- BZOJ 3907: 网格( 组合数 + 高精度 )
(0,0)->(n,m)方案数为C(n,n+m), 然后减去不合法的方案. 作(n,m)关于y=x+1的对称点(m-1,n+1), 则(0,0)->(m-1,n+1)的任意一条路径都对应( ...
- bzoj 3907 网格 bzoj2822 [AHOI2012]树屋阶梯——卡特兰数(阶乘高精度模板)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3907 https://www.lydsy.com/JudgeOnline/problem.p ...
- BZOJ 3907: 网格【组合数学】
Description 某城市的街道呈网格状,左下角坐标为A(0, 0),右上角坐标为B(n, m),其中n >= m.现在从A(0, 0)点出发,只能沿着街道向正右方或者正上方行走,且不能经过 ...
- [Catalan数三连]网格&有趣的数列&树屋阶梯
如何让孩子爱上打表 Catalan数 Catalan数是组合数学中一个常出现在各种计数问题中的数列. 以比利时的数学家欧仁·查理·卡塔兰 (1814–1894)的名字来命名. 先丢个公式(设第n项为$ ...
- BZOJ 1485: [HNOI2009]有趣的数列 [Catalan数 质因子分解]
1485: [HNOI2009]有趣的数列 Description 我们称一个长度为2n的数列是有趣的,当且仅当该数列满足以下三个条件: (1)它是从1到2n共2n个整数的一个排列{ai}: (2)所 ...
- BZOJ 1856: [Scoi2010]字符串 [Catalan数]
1856: [Scoi2010]字符串 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1418 Solved: 790[Submit][Status][ ...
随机推荐
- 【多线程】 Task
[多线程] Task 一. 常用方法: 1. ContinueWith : 当前 Task 完成后, 执行传入的 Task 2. Delay : 创建一个等待的 Task,只有在调用 Wait 方法时 ...
- javac、jar使用实录
因项目管理部署需要,记录一下过程,以免下次忘记了,再次使用又需要重头再来,只记录正确的操作方式,可能会提到某些错误 建立项目所在目录F:\www 案例一 其下建立项目的java源文件的包目录结构.ja ...
- 标志寄存器PSW和汇编条件转移指令解释
标志寄存器PSW 标志寄存器PSW(程序状态字寄存器PSW) 标志寄存器PSW是一个16为的寄存器.它反映了CPU运算的状态特征并且存放某些控制标志.8086使用了16位中的9位,包括6个状态标志 ...
- Ubuntu 安装Google浏览器
Ubuntu自带的浏览器是火狐浏览器,使用的时候多多少少有些不方便,这里安装Googel浏览器. 下载 可以到 Ubuntu chrome去下载安装包. 安装 首先到下载的根目录 cd ~/Downl ...
- Qt Qwdget 汽车仪表知识点拆解8 淡入效果
先贴上效果图,注意,没有写逻辑,都是乱动的 看下面的开始,开始的时候有一个带入的效果,这里有一个坑, 网上大部分都是调用下面这个函数 setWindowOpacity(); 但是,你会发现,在你的子窗 ...
- jmeter之HTTP请求
1.添加一个线程组:Test plan_添加_Threads(users)_线程组(右键操作),如下图: 2.添加一个HTTP请求:线程组_添加_sample_HTTP请求(右键操作),如下图: 3. ...
- github 初始化操作小记
Git作为一种越来越重要的工具,github又如此流行,现在就简单记录一下git的基础操作,希望能帮助大家快速体验入门! 1 查看本地是否存在”公钥”和”私钥” 如果没有,则执行: ssh-keyg ...
- Unity动态换装之Spine换装
注:转载请注明转载,并附原链接 http://www.cnblogs.com/liaoguipeng/p/5867510.html 燕双飞情侣 一.动态换装原理 换装,无非就是对模型的网格,或者贴图进 ...
- 深挖 NGUI 基础 之UIRoot (一)
当你开始使用NGUI的时候,简单的从项目视图 中一个”Control”预设体 拖拽到场景视图中,你将会发现 Hierarchy层次面板中会出现以下层次结构: 其中 UI Root作为根节点,是每个NG ...
- 【page.js】配置及Page函数说明
页面.js中的Page函数用来注册一个页面,指定页面的初始数据.生命周期回调.事件处理函数等. 语法:Page(Object)参数: Object json对象 Page({ /** * data * ...