bzoj3907: 网格

来源:互联网 发布:写c语言是用记事本么 编辑:程序博客网 时间:2024/05/17 03:59

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3907

题意:中文题。。。

分析:用卡特兰数的非常规法证明F[n]=C(2*n,n)-C(2*n,n-1)那种方法可以分析出这题的答案为C(n+m,n)-C(n+m,n+1),详见百度百科,再用高精度处理一下即可。

代码:

#include<map>#include<set>#include<cmath>#include<queue>#include<math.h>#include<cstdio>#include<vector>#include<string>#include<cstring>#include<iostream>#include<algorithm>#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;const int N=10010;const int MAX=151;const int MOD1=100000007;const int MOD2=100000009;const double EPS=0.00000001;typedef long long ll;const ll MOD=1000000007;const ll INF=10000000010;typedef unsigned long long ull;int a[N],b[N],q[N],num[N];void deal(int n) {    int i,j,k=0;    memset(q,0,sizeof(q));    for (i=2;i<=n;i++) {        if (!q[i]) { a[++k]=i;b[i]=i; }        for (j=1;j<=k;j++) {            if (a[j]*i>n) break ;            q[a[j]*i]=1;b[a[j]*i]=a[j];            if (i%a[j]==0) break ;        }    }}int ans[N];void mul(int x) {    for (int i=1;i<=ans[0];i++) ans[i]*=x;    for (int i=1;i<ans[0];i++) { ans[i+1]+=ans[i]/10;ans[i]%=10; }    while (ans[ans[0]]>9) {        ans[ans[0]+1]=ans[ans[0]]/10;        ans[ans[0]]%=10;ans[0]++;    }}int main(){    int i,j,n,m;    scanf("%d%d", &n, &m);    deal(n+m);    for (i=1;i<=n;i++) num[i]--;    for (i=1;i<=m;i++) num[i]--;    for (i=1;i<=n+m;i++) num[i]++;    num[n-m+1]++;num[n+1]--;    for (i=n+m;i>1;i--)    if (!q[i]) continue ;    else {        num[b[i]]+=num[i];num[i/b[i]]+=num[i];num[i]=0;    }    memset(ans,0,sizeof(ans));    ans[0]=ans[1]=1;    for (i=2;i<=n+m;i++)        for (j=1;j<=num[i];j++) mul(i);    for (i=ans[0];i>0;i--) printf("%d", ans[i]);    printf("\n");    return 0;}


0 0
原创粉丝点击