http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11562&courseid=0

求n边形分解成三角形的方案数。

就是求n-2个卡特兰数,从大神那盗取了一份模板,效率极高.同时也很复杂.

 #include <cstdio>
#include <cmath>
#include <stdlib.h>
#include <memory.h>
typedef int typec;
typec GCD(typec a, typec b)
{
return b? GCD(b, a % b) : a;
}
typec extendGCD(typec a, typec b, typec& x, typec& y)
{
if(!b) return x = , y = , a;
typec res = extendGCD(b, a % b, x, y), tmp = x;
x = y, y = tmp -(a/b)*y;
return res;
}
typec power(typec x, typec k)
{
typec res = ;
while(k)
{
if(k&) res *= x;
x *= x, k >>= ;
}
return res;
}
typec powerMod(typec x, typec k, typec m)
{
typec res = ;
while(x %= m, k)
{
if(k&) res *= x, res %= m;
x *= x, k >>= ;
}
return res;
}
typec inverse(typec a, typec p, typec t = )
{
typec pt = power(p, t);
typec x, y;
y = extendGCD(a, pt, x, y);
return x < ? x += pt : x;
}
typec linearCongruence(typec a, typec b, typec p, typec q)
{
typec x, y;
y = extendGCD(p, q, x, y);
x *= b - a, x = p * x + a, x %= p * q;
if(x < ) x += p * q;
return x;
}
const int PRIMEMAX = ;
int prime[PRIMEMAX + ];
int getPrime()
{
memset(prime, , sizeof(int) * (PRIMEMAX + ));
for(int i = ; i <= PRIMEMAX; i++)
{
if(!prime[i]) prime[++prime[]] = i;
for(int j = ; j <= prime[] && prime[j] <= PRIMEMAX/i; j++)
{
prime[prime[j]*i] = ;
if(i % prime[j] == ) break;
}
}
return prime[];
}
int factor[][], facCnt;
int getFactors(int x)
{
facCnt = ;
int tmp = x;
for(int i = ; prime[i] <= tmp / prime[i]; i++)
{
factor[facCnt][] = , factor[facCnt][] = ;
if(tmp % prime[i] == )
factor[facCnt][] = prime[i];
while(tmp % prime[i] == )
factor[facCnt][]++, factor[facCnt][] *= prime[i], tmp /= prime[i];
if(factor[facCnt][]) facCnt++;
}
if(tmp != ) factor[facCnt][] = tmp, factor[facCnt][] = tmp, factor[facCnt++][] = ;
return facCnt;
}
typec combinationModPt(typec n, typec k, typec p, typec t = )
{
if(k > n) return ;
if(n - k < k) k = n - k;
typec pt = power(p, t);
typec a = , b = k + , x, y;
int pcnt = ;
while(b % p == ) pcnt--, b /= p;
b %= pt;
for(int i = ; i <= k; i++)
{
x = n - i + , y = i;
while(x % p == ) pcnt++, x /= p;
while(y % p == ) pcnt--, y /= p;
x %= pt, y %= pt, a *= x, b *= y;
a %= pt, b %= pt;
}
if(pcnt >= t) return ;
extendGCD(b, pt, x, y);
if(x < ) x += pt;
a *= x, a %= pt;
return a * power(p, pcnt) % pt;
}
const typec PTMAX = ;
typec facmod[PTMAX];
void initFacMod(typec p, typec t = )
{
typec pt = power(p, t);
facmod[] = % pt;
for(int i = ; i < pt; i++)
{
if(i % p) facmod[i] = facmod[i - ] * i % pt;
else facmod[i] = facmod[i - ];
}
}
typec factorialMod(typec n, typec &pcnt, typec p, typec t = )
{
typec pt = power(p, t), res = ;
typec stepCnt = ;
while(n)
{
res *= facmod[n % pt], res %= pt;
stepCnt += n /pt, n /= p, pcnt += n;
}
res *= powerMod(facmod[pt - ], stepCnt, pt);
return res %= pt;
}
typec combinationModPtFac(typec n, typec k, typec p, typec t = )
{
if(k > n || p == ) return ;
if(n - k < k) k = n - k;
typec pt = power(p, t), pcnt = , pmcnt = ;
if(k < pt) return combinationModPt(n, k, p, t);
initFacMod(p, t);
typec a = factorialMod(n, pcnt, p, t);
typec b = factorialMod(k, pmcnt, p, t);
b *= b, pmcnt <<= , b %= pt;
typec tmp = k + ;
while(tmp % p == ) tmp /= p, pmcnt++;
b *= tmp % pt, b %= pt;
pcnt -= pmcnt;
if(pcnt >= t) return ;
a *= inverse(b, p, t), a %= pt;
return a * power(p, pcnt) % pt;
}
typec combinationModFac(typec n, typec k, typec m)
{
getFactors(m);
typec a, b, p, q;
for(int i = ; i < facCnt; i++)
{
if(!i) a = combinationModPtFac(n, k, factor[i][], factor[i][]), p = factor[i][];
else b = combinationModPtFac(n, k, factor[i][], factor[i][]), q = factor[i][];
if(!i) continue;
a = linearCongruence(a, b, p, q), p *= q;
}
return a;
}
int main()
{
getPrime();
typec n, k;
while(scanf("%d %d", &n, &k) != EOF)
printf("%d\n", combinationModFac( * (n-), n-, k));
return ;
}

HUNAN 11562 The Triangle Division of the Convex Polygon(大卡特兰数)的更多相关文章

  1. HOJ 13101 The Triangle Division of the Convex Polygon(数论求卡特兰数(模不为素数))

    The Triangle Division of the Convex Polygon 题意:求 n 凸多边形可以有多少种方法分解成不相交的三角形,最后值模 m. 思路:卡特兰数的例子,只是模 m 让 ...

  2. HNU 13101 The Triangle Division of the Convex Polygon 组合数的因式分解求法

    题意: 求第n-2个Catalan数 模上 m. 思路: Catalan数公式: Catalan[n] = C(n, 2n)/(n+1) = (2n)!/[(n+1)!n!] 因为m是在输入中给的,所 ...

  3. [LeetCode] Convex Polygon 凸多边形

    Given a list of points that form a polygon when joined sequentially, find if this polygon is convex ...

  4. Leetcode: Convex Polygon

    Given a list of points that form a polygon when joined sequentially, find if this polygon is convex ...

  5. ACM训练联盟周赛 G. Teemo's convex polygon

    65536K   Teemo is very interested in convex polygon. There is a convex n-sides polygon, and Teemo co ...

  6. 【LeetCode】469. Convex Polygon 解题报告(C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 计算向量夹角 日期 题目地址:https://leet ...

  7. HDU 5914 Triangle(打表——斐波那契数的应用)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5914 Problem Description Mr. Frog has n sticks, whos ...

  8. HDU 4195 Regular Convex Polygon

    思路:三角形的圆心角可以整除(2*pi)/n #include<cstdio> #include<cstring> #include<iostream> #incl ...

  9. POJ 3410 Split convex polygon(凸包)

    题意是逆时针方向给你两个多边形,问你这两个多边形通过旋转和平移能否拼成一个凸包. 首先可以想到的便是枚举边,肯定是有一对长度相同的边贴合,那么我们就可以n2枚举所有边对,接下来就是旋转点对,那么假设多 ...

随机推荐

  1. python_111_动态导入模块

    lib下aa.py文件内容: class C: def __init__(self): self.name='alex' from lib import aa#正常导入 print(aa.C) 动态导 ...

  2. shell脚本,配置文件加载顺序,以及什么时候加载。

    在linux系统中,有/etc/profile,/etc/bashrc ,~/.bash_profile,~/bashrc这四个配置文件,这些文件,会自动的在某些时候加载,也就是点一下,一般都是些别名 ...

  3. Broadcast BCM94322 用ubuntu修改ID

    1.按这个教程的6楼做的http://bbs.pcbeta.com/viewthread-1324168-1-1.html.注意我先下载 的是ubuntu9.05版本,做U盘启动进live 模式,43 ...

  4. 自写小函数处理 javascript 0.3*0.2 浮点类型相乘问题

    const reg = /^([-+]?)([0-9]+)\.([0-9]*)$/; // 判断是不是浮点数 const isFloat = function(number){ return reg. ...

  5. 对linux中source,fork,exec的理解以及case的 使用

    fork   使用 fork 方式运行 script 时, 就是让 shell(parent process) 产生一个 child process 去执行该 script, 当 child proc ...

  6. poj--2139

    Description The cows have been making movies lately, so they are ready to play a variant of the famo ...

  7. cf950f Curfew

    神贪心--写了一个晚上加一个早上. 先考虑只有一个宿管的情况. 首先,如果这个宿舍人多了,多余的人就跑到下一个宿舍.(如果这是最后一个宿舍的话,多的就躺床底下) 如果这个宿舍人少了,但是能从别的宿舍调 ...

  8. linux -- 查找(find)命令 一

    find: find命令是非常有用的linux命令,我们可以用它来根据指定的搜索条件来搜索整个文件系统来查找文件或目录. 基本的‘find file’命令 find . -name "foo ...

  9. hdu2087

    #include <stdio.h> #include <string.h> int main(){ int cnt,i,j,k; +],tmp[+]; int strl,tm ...

  10. hdu2022

    #include <stdio.h> #include <math.h> #define here puts("go,go,go!\n") int main ...