喵哈哈村的魔法考试 Round #7 (Div.2) E

喵哈哈村的小美

发布时间: 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 }
原文地址:https://www.cnblogs.com/ledoc/p/6557133.html