2017百度之星初赛(B) 1001 Chess(思维+Lucas)

来源:互联网 发布:软件评测师培训费用 编辑:程序博客网 时间:2024/06/06 01:14

题目大意:

给你一个 m*n (0< m <1000,0< n <1000)的棋盘,问你在上面放最多的棋子的摆放方法的种数。要求:对于每一个棋子,它的上面每一行的棋子都必须在它的左边。且每一行只能有一个棋子。

分析:

其实仔细考虑,这个问题对棋盘来说是对角线对称的,所以 m n 的顺序对这道题的结果无关。所以现在我们不妨假设:m>n。首先最多能放的棋子个数肯定是:min(n,m)。然后我们考虑这样一个问题:对于一个m*1的表格,我从中选出 n 个格子放棋子,对于每一种放这 n 个棋子的方式,我将这n个棋子上移至符合要求,都有且只有一种在 n*m 的格子中放这 n 个棋子的方式与其对应。那么,显然总共的摆放方式就是:Cnm

代码:

#include<bits/stdc++.h>#define LL long longusing namespace std;const int mod=1000000007;int t,m,n;LL qmod(LL x,int n)//快速幂取模{      LL ans=1;      for(;n;n>>=1)      {            if(n&1)ans=(ans*x)%mod;            x=x*x%mod;      }      return ans;}LL C(int n,int m)//组合数取模{      if(m>n)return 0;      LL ans=1;      for(int i=1;i<=m;i++)      {            ans=ans*((n-m+i)*qmod(i,mod-2)%mod)%mod;      }      return ans;}int main(){    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&n,&m);//n<m        int temp=0;        if(n>m)        {            temp=n;            n=m;            m=temp;        }        printf("%d\n",C(m,n)%mod);    }}