您的位置:首页 > 其它

BZOJ 3907: 网格 组合数 高精度

2017-08-19 16:47 267 查看

3907: 网格

Time Limit: 1 Sec  Memory Limit: 256 MB
Submit: 466  Solved: 215

[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

输出文件中仅有一个整数和一个换行/回车符,表示不同的方案总数。

Sample Input

6 6

Sample Output

132

HINT

100%的数据中,1 <= m <= n <= 5 000

高精度真是我的梦魇。。不说了。。

不考虑直线到达(n,m)答案为C(n+m,n)

这是加上直线

令n>m (有关系的,看完后面可以画图看一看)

作(n,m)关于y=x+1的对称点

此时新矩形(m-1,n+1)的所有路径都为不符合条件的路径
所以最后答案为
C(n+m,n)-(n+m,n+1)

#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<map>
#include<set>
using namespace std;

inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
void print(int x)
{if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');}

const int N=10100;

int num
,num2
;

inline void cont(int *a,int l,int r,int p)
{
register int i,j,x;
for(i=l;i<=r;++i)
{x=i;for(j=2;(j*j)<=x;++j){while(x%j==0){x/=j;a[j]+=p;}}if(x)a[x]+=p;}
}

struct bignum
{
int a
;

friend bignum operator *(const bignum &x,int y)
{
bignum b=x;
register int i;
for(i=1;i<=b.a[0];i++)b.a[i]*=y;
for(i=1;i<=b.a[0];i++){if(b.a[i]>=10){b.a[i+1]+=b.a[i]/10;b.a[i]%=10;b.a[0]=max(b.a[0],i+1);}}
return b;
}

friend bignum operator -(const bignum &x,const bignum &y)
{
bignum b=x;
register int i;
for(i=1;i<=y.a[0];i++){b.a[i]-=y.a[i];}
for(i=1;i<=b.a[0];i++)while(b.a[i]<0){b.a[i]+=10;b.a[i+1]--;}
while(b.a[0]>1&&!b.a[b.a[0]])b.a[0]--;
return b;
}
};

int main()
{
int n=read(),m=read();
register int i;
if(n<m)swap(n,m);
cont(num,2,n,-1);cont(num,m+1,n+m,1);
cont(num2,2,n+1,-1);cont(num2,m,n+m,1);
bignum a,b;
a.a[0]=b.a[0]=1;a.a[1]=b.a[1]=1;
for(i=2;i<=N;++i)while(num[i]--)a=a*i;
for(i=2;i<=N;++i)while(num2[i]--)b=b*i;
a=a-b;
for(i=a.a[0];i;i--)print(a.a[i]);puts("");
return 0;
}
/*
6 6

132
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: