BZOJ 3907: 网格 [Catalan数 高精度]
3907: 网格
Time Limit: 1 Sec Memory Limit: 256 MBSubmit: 402 Solved: 180
[Submit][Status][Discuss]
Description
某城市的街道呈网格状,左下角坐标为A(0, 0),右上角坐标为B(n, m),其中n >= m。现在从A(0, 0)点出发,只能沿着街道向正右方或者正上方行走,且不能经过图示中直线左上方的点,即任何途径的点(x, y)都要满足x >= y,请问在这些前提下,到达B(n, m)有多少种走法。
Input
输入文件中仅有一行,包含两个整数n和m,表示城市街区的规模。
Output
输出文件中仅有一个整数和一个换行/回车符,表示不同的方案总数。
100%的数据中,1 <= m <= n <= 5 000
你们出题人有意思吗,变式套上高精度又一道题.....
问题在于我这个傻叉横纵坐标竟然搞混了
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; typedef long long ll; const int N=1e4+5; inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } int n,m; bool notp[N]; int p[N],lp[N]; void sieve(int n){ for(int i=2;i<=n;i++){ if(!notp[i]) p[++p[0]]=i,lp[i]=p[0]; for(int j=1;j<=p[0]&&i*p[j]<=n;j++){ notp[i*p[j]]=1; lp[i*p[j]]=j; if(i%p[j]==0) break; } } } struct Big{ int d[N],l; Big():l(1){memset(d,0,sizeof(d));d[1]=1;} int& operator[](int x){return d[x];} }a,b; void Mul(Big &a,int b){ int g=0; for(int i=1;i<=a.l;i++){ g+=a[i]*b; a[i]=g%10; g/=10; } for(;g;g/=10) a[++a.l]=g%10; } void Minus(Big &a,Big &b){ for(int i=1;i<=b.l;i++){ if(a[i]<b[i]) a[i]+=10,a[i+1]--; a[i]-=b[i]; } int p=b.l+1; while(a[p]<0) a[p]+=10,a[p+1]--; while(a[a.l]==0) a.l--; } void Print(Big &a){ for(int i=a.l;i>=1;i--) printf("%d",a[i]); } int e[N]; inline void add(int x,int d){ while(x!=1){ e[lp[x]]+=d; x/=p[lp[x]]; } } void C(int n,int m,Big &ans){ memset(e,0,sizeof(e)); for(int i=n;i>=n-m+1;i--) add(i,1); for(int i=2;i<=m;i++) add(i,-1); for(int j=1;j<=p[0];j++) for(;e[j];e[j]--) Mul(ans,p[j]); } int main(){ freopen("in","r",stdin); n=read();m=read(); sieve(n+m); C(n+m,n,a); C(n+m,n+1,b); Minus(a,b); Print(a); }
Copyright:http://www.cnblogs.com/candy99/