某城市的街道呈網格狀,左下角座標爲A(0, 0),右上角座標爲B(n, m),其中n >= m。如今從A(0, 0)點出發,只能沿着街道向正右方或者正上方行走,且不能通過圖示中直線左上方的點,即任何途徑的點(x, y)都要知足x >= y,請問在這些前提下,到達B(n, m)有多少種走法。
spa
輸入文件中僅有一行,包含兩個整數n和m,表示城市街區的規模。code
輸出文件中僅有一個整數和一個換行/回車符,表示不一樣的方案總數。blog
50%的數據中,n = m,在另外的50%數據中,有30%的數據:1 <= m < n <= 100
100%的數據中,1 <= m <= n <= 5 000ip
首先,咱們不考慮這條線的狀況,則從(0,0)走到(n,m)的方案數則爲\(C_{m+n}^{m}\)
而咱們如今只須要考慮非法的狀況
由於不能超過y=x的直線,因此其實至關於不能碰到y=x+1這條線
作出(n,m)關於y=x+1的對稱點M
則M(m-1,n+1)
從(0,0)走到(n,m)的非法方案至關於從 (0,0)走到M的方案,即\(C^{m-1}_{n+m}\)
則答案則爲input
答案過大,要高精度處理
做者不會高精度除高精度,因此直接從2~m一個個的除
友情提示:高精度不壓位會T飛,請慎重考慮
io
#include <cstdio> #define MO 1000000000 using namespace std; int n,m,i,x; long long a[100001],b[100001],c[100001]; void cheng(int w) { int t=w,x;a[0]=0; while (t) { a[++a[0]]=t%MO; t/=MO; } for (int i=1;i<=c[0];i++) { x=0; for (int j=1;j<=a[0];j++) { b[i+j-1]+=c[i]*a[j]+x; x=b[i+j-1]/MO; b[i+j-1]%=MO; } b[i+a[0]]=x; } c[0]+=a[0]; if (!b[c[0]]) c[0]--; for (int i=1;i<=c[0];i++) c[i]=b[i],b[i]=0; } void chu(int w) { long long t=0,x=0; for (int i=c[0];i>=1;i--) { t=t*MO+c[i]; c[i]=t/w; t=t%w; } while (!c[c[0]])c[0]--; } int main() { scanf("%d%d",&n,&m); c[1]=n+2;c[0]=1; for (i=n+3;i<=n+m;i++) { cheng(i); } cheng(n-m+1); for (i=2;i<=m;i++) { chu(i); } printf("%lld",c[c[0]]); for (i=c[0]-1;i>=1;i--) { printf("%09lld",c[i]); } }