51nod-1627 瞬间移动(组合数+逆元)
题目描述:
有一个无限大的矩形,初始时你在左上角(即第一行第一列),每次你都可以选择一个右下方格子,并瞬移过去(如从下图中的红色格子能直接瞬移到蓝色格子),求到第n行第m列的格子有几种方案,答案对1000000007取模。
Input
单组测试数据。 两个整数n,m(2<=n,m<=100000)
Output
一个整数表示答案。
Input示例
4 5
Output示例
10
题目分析:定义f(n,m)为从左上角走到(n,m)的所有方案数。显然有f(n,m)=∑ ∑ f(i,j),其中1≤i<n、j≤1<m。这是组合数。
代码如下:
#include <stdio.h> #include <string> #include <cstring> #include <map> #include <set> #include <math.h> #include <queue> #include <stack> #include <vector> #include <algorithm> //#define _COMPLIE #ifdef _COMPLIE #include "51nod_1627.h" #endif // _COMPLIE using namespace std; typedef long long LL; const int mod=1000000007; const int N=200000; class nod_1627 { private: int n,m; LL c[N+5]; void getC(int x); LL myPow(LL a,int x); public: void input(); void process(); void output(); }; void nod_1627::input() { scanf("%d%d",&n,&m); } LL nod_1627::myPow(LL a,int x) { LL res=1; while(x){ if(x&1) res=(res*a)%mod; a=(a*a)%mod; x>>=1; } return res; } void nod_1627::getC(int x) { c[0]=c[x]=1; c[1]=c[x-1]=x; for(int i=2;i<=x/2;++i){ c[x-i]=c[i]=(((c[i-1]*(LL)(x-i+1))%mod)*myPow(i,mod-2))%mod; } } void nod_1627::process() { --n,--m; getC(n+m-2); } void nod_1627::output() { printf("%lld\n",c[m-1]); } int main() { //freopen("in.txt","r",stdin); nod_1627 problem; problem.input(); problem.process(); problem.output(); return 0; }