我怎么也没想到,还有竟然会这么难,心态爆炸,数学是真正的瓶颈:
首先,这个一看就是大数,
1)其中第一个思想 逆元 ,什么意思呢?
(1/n)%p 会出现一个大问题,精度问题 ======》 如果设 a = 1/n 呢?
(1/n)%p = 1*a%p = a/b* b*a %p 哈哈解决 ===
2) 费马小定理
在模为素数p的情况下,有费马小定理 a^(p-1)=1(mod p)
那么a^(p-2)=a^-1(mod p) 也就是说a的逆元为a^(p-2)
而在模不为素数p的情况下,有欧拉定理 a^phi(m)=1(mod m) (a⊥m)
同理a^-1=a^(phi(m)-1)
因此逆元x便可以套用快速幂求得了x=a^(phi(m)-1)
但是似乎还有个问题?如何判断a是否有逆元呢?
检验逆元的性质,看求出的幂值x与a相乘是否为1即可
PS:这种算法复杂度为O(log2N)在几次测试中,常数似乎较上种方法大
当p比较大的时候需要用快速幂求解
3)逆元打表时候的小技巧:经典
inv[i] = inv[i+1]*(i+1)%mod;4. 快速幂 a^b
ll Pow (ll a ,ll b){ ll ans =1; while(b){ if(b%2==1) ans =ans*a%mod; a=a*a%mod; b>>=1; } return ans; }5)卡特兰数
n个左括号,m个右括号的合法组合 ======>C(n,n+m)-C(n+1,n+m)
看了半个小时,恍然大悟,就是二分平面,然后上下调整
应用:(注意一定要记笔记 )
1.n个节点构成的二叉树,共有多少种情形?
2.一个栈(无穷大)的进栈序列为1,2,3,…,n,有多少个不同的出栈序列
3.类似问题,买票找零
4.n*n棋盘从左下角走到右上角而不穿过主对角线的走法
5.、求一个凸多边形区域划分成三角形区域的方法数?
6.矩阵连乘的括号化
7.在圆上选择2n个点,将这些点成对连接起来使得所得到的n条线段不相交的方法数?
WYF正试图用一个栈来构造一棵树,现在他已经构造了
n个元素作为树的节点,只要将这
n个元素依次入栈出栈就可以形成一棵树了。当然,这个问题与树并没有关系,所以它叫做
WYF的栈。每次你可以入栈一个新元素或者当栈非空时出栈一个元素,
n个元素必须依次入栈,而
WYF希望其中第
m个元素入栈之后,栈中恰好有
k个元素,现在他想知道一共有多少种入栈出栈顺序满足这个条件。
输入描述:
第一行一个正整数T,表示数据组数。(1<=T<=10000) 对于每组数据包含一行三个正整数n,m,k。
输出描述:
对于每组数据输出一个正整数表示答案。由于答案可能过大,所以只需要输出对10 9+7取模后的答案
示例1
输入
2 3 3 3 3 3 2
输出
1 2
示例2
输入
5 10 3 2 10 2 2 10 7 5 10 6 2 10 7 6
输出
6864 11934 2200 3780 924
示例3
输入
2 5 4 4 5 2 1
输出
5 14
备注:
1<=n,m,k<=106
#include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #include <cmath> #include <vector> #include <queue> using namespace std; #define INF 0x7f typedef long long ll ; #define f(i,l,r) for(int i=l;i<=r;++i) #define g(i,l,r) for(int i=l;i>=r;--i) #define mod 1000000007 const int N = 2000000; ll jc[N+5]={1},inv[N+5]={1}; ll Pow(ll a ,ll b); //a^b ll Cata(ll a ,ll b); //卡特兰数 ll C( ll n ,ll m); int main(){ //阶乘和逆元打表 f(i,1,2000001) jc[i]=jc[i-1]*i%mod; //费马小定理 inv[2000001] = Pow(jc[2000001],mod-2); g(i,N,1) inv[i] = inv[i+1]*(i+1)%mod; int t ; int n,m,k; cin>>t; while(t--){ cin>>n>>m>>k; cout<<Cata(m-1,m-k)*Cata(n-(m-k),n-m)%mod<<endl; } return 0; } ll Pow (ll a ,ll b){ ll ans =1; while(b){ if(b%2==1) ans =ans*a%mod; a=a*a%mod; b>>=1; } return ans; } ll Cata(ll a ,ll b){ return (C(a+b,a)-C(a+b,a+1)+mod)%mod; } ll C( ll n ,ll m){ return n<m? 0:jc[n]*inv[m]%mod*inv[n-m]%mod; }
未来的我一定会感谢正在努力的现在的我!