喵哈哈村的小美
发布时间: 2017年3月13日 12:40 时间限制: 1000ms 内存限制: 128M
为了拯救喵哈哈村,这个世界必须要存在英雄。
一名叫做小美的英雄站了出来!他现在面临一个难题:
小美在玩一个游戏,她需要把1, 2, 3, ... NM填入一个N行M列的矩阵中,使得矩阵每一行从左到右、每一列从上到下都是递增的。
例如如下是3x3的一种填法:
136
247
589
给定N和M,她希望知道一共有多少种不同的填法。
本题包含若干组测试数据。
一行包含两个整数N和M。
满足:1 <= N <= 3, 1 <= M <= 100000
输出一共有多少种不同的填法。由于结果可能很大,你只需输出答案模10^9+7的余数。
复制
3 2
5
不会做...
然后看题解...
好像get新的知识点了...
原来看扩展欧几里得的时候,了解过逆元,也写过一次,但是感觉没什么用...就忘记了
现在看来还是要多做题去领悟每一个知识点的妙处...
扩展欧几里得的一个用处就是用来求逆元---逆元(a/b%m 等价于 a*c%m c就是b的逆元)
求逆元的过程如下
1 int ext_gcd(int a, int b, int &x, int &y){ 2 if(b==0){ 3 x=1; 4 y=0; 5 }else{ 6 ext_gcd(b, a%b, x, y); 7 int tem=x; 8 x=y; 9 y=tem-(a/b)*y; 10 } 11 return a; 12 } 13 int mod_inverse(int a, int m){ 14 int x, y; 15 ext_gcd(a, m, x, y); 16 return (m+x%m)%m; 17 }
这样除法取模就转换成了乘法取模!
然后这题又涉及到数学问题,杨氏矩阵 牵扯到一个屌屌的公式---钩子公式!
这个大佬的链接有详细的介绍 http://blog.csdn.net/acdreamers/article/details/14549077
就是一个特殊的很强的矩阵
这个题目里面好像又有一个很强的公式 两行和三行的时候分开讨论一下
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 const int maxn=1e6+6; 6 const int mod=1e9+7; 7 8 int ext_gcd(int a, int b, int &x, int &y){ 9 if(b==0){ 10 x=1; 11 y=0; 12 }else{ 13 ext_gcd(b, a%b, x, y); 14 int tem=x; 15 x=y; 16 y=tem-(a/b)*y; 17 } 18 return a; 19 } 20 int mod_inverse(int a, int m){ 21 int x, y; 22 ext_gcd(a, m, x, y); 23 return (m+x%m)%m; 24 } 25 inline int mul(int a, int b){return int(1ll*a*b%mod);}; 26 inline int add(int a, int b){return a+b>=mod?a+b-mod:a+b;}; 27 inline int sub(int a, int b){return a-b<0?a-b+mod:a-b;} 28 inline int _div(int a, int b){return mul(a, mod_inverse(b, mod));} 29 long long p[maxn]; 30 long long solve1(int x){ 31 return _div(p[2*x], mul(p[x], p[x+1])); //这个公式很强 32 } 33 long long solve2(int x){ 34 return _div(mul(2, p[3*x]), mul(p[x], mul(p[x+1], p[x+2]))); 这个公式也很强 35 } 36 int main(){ 37 p[0]=1; 38 for(int i=1; i<maxn; i++) 39 p[i]=p[i-1]*i%mod; 40 int n,m; 41 while(cin>>n>>m){ 42 if(n==1) cout<<"1"<<endl; 43 else if(n==2) cout<<solve1(m)<<endl; 44 else cout<<solve2(m)<<endl; 45 } 46 return 0; 47 }