描述:
Fate是讲述这一场围绕着圣杯而展开的战斗。在战斗中的七个参与者可以召唤出一个历史上的英雄,来为自己战斗。不过这样有很多弊端,比如说会引发一些历史遗留问题(兰斯洛特见到亚瑟王什么的,项羽见到刘邦什么的…………)。而且有时还会引发不必要的误会,比如下面一例:
最近,吉尔.德.莱斯一直缠着亚瑟王,而且还说他是圣女贞德再世,以此引发了一系列的骚扰。终于有一天,亚瑟王忍无可忍了,决定去讨伐莱斯。作为一个小有名气的法师,莱斯的保护措施是很完善的。
他有m面不同颜色的每条边均不等的n边凸边形的魔法盾。亚瑟王的每一次攻击都是将一个凸多边形延其某个对角线斩开,使其变为两个凸多边形。当在一种颜色的凸多边形的魔法盾中只有三角形时,就会变得能量不稳定,这时只要消灭其中一个三角形,这种颜色的能量盾就会消失。问:亚瑟王如果要完全破处莱斯的防御有多少种不同的方式?(斩击无先后顺序的区别)
Input
每一行有一个m,n(3<n<10^18,1<=m<10^18)
Output
每一行输出一个可能的放法数(模10007取余)
Sample Input
1 3
2 4
Sample Output
1
4
解题思路:
== 分析 ==
考虑1块n边形魔法盾的情况, 设有cata[n]种分割成三角形的办法,则答案为cata[n],当有m个魔法盾时,每个都有cata[n]种办法,所以答案为cata[n]的m次幂
这里的cata[n]就属于卡塔兰数列,具体地说n边形的三角形剖分方案数是卡塔兰数列的第n-2项.
== 卡塔兰数 ==
公式为c(2*n,n)/(n+1), 考虑到求模的问题这个形式很不方便, 可以展开成c(n,2*n)-c(n+1,2*n) (通过顶端链接可以查到),将组合数按定义展开,略作计算就能达到.
卡塔兰数的通项公式可以利用它的递归性质,通过生成函数得到,具体可以参考<<The art and craft of problem solving>>
(中文名:怎样解题,不是波利亚那部,图书馆就有,不过要等我先还......囧)
卡塔兰数有很多奇妙的性质,诞生出很多经典问题,有必要深入了解,传说有本名为<<具体数学>>的奇书记载着卡塔兰数的组合证明,有缘的话30就能买到=。=...
== 卢卡斯定理 ==
本题需要对组合数求模,当n取某些值时,不与模数p互素,无法求其逆元,需要利用卢卡斯定理.
#include<iostream>
using namespace std;
const int P = 10007;
long long fastPow(long long x,long long y,int p)
{
long long ans = 1;
while(y)
{
if(y&1)
ans = ans*x%p;
y >>= 1;
x = x*x%p;
}
return ans;
}
long long factorial[P+1];
void init(long long p)
{
factorial[0] = 1;
for(int i = 1;i <= p;i++)
factorial[i] = factorial[i-1]*i%p;
}
long long Lucas(long long a,long long k,long long p) //求C(n,m)%p p最大为10^5。a,b可以很大!
{
long long re = 1;
while(a && k)
{
long long aa = a%p;long long bb = k%p;
if(aa < bb) return 0;
re = re*factorial[aa]*fastPow(factorial[bb]*factorial[aa-bb]%p,p-2,p)%p;//这儿的求逆不可先处理
a /= p;
k /= p;
}
return re;
}
long long getCatan(long long n)
{
return (Lucas(2*n,n,P)-Lucas(2*n,n+1,P)+P)%P;
}
int main()
{
long long n,m;
init(P);
while(cin>>m>>n)
{
m %=(P-1);
n = getCatan(n-2);
cout<<fastPow(n,m,P)<<endl;
}
return 0;
}
最后欢迎大家访问我的个人网站: 1024s