• 51nod1486 大大走格子


    n<=100000 * m<=100000的网格求不经过给定的h<=2000个点,从左上角到右下角只向右或向下走的方案数。

    先来看不经过一个点:

    要绕过这个点到右下角,可以先到该点右上角,再下来,或者到该点左下角,再往右。更一般的,是到该点右下角的总方案,减去经过该点的方案数。

    如果这个点坐标(n,m),那么到右下角,方案数就是S(n+1,m+1)-S(n,m),其中S(i,j)=C(i+j,j),是到点(i,j)的所有方案数,自行推导。

    那如果有多个点呢?我们需要不重复、不遗漏地统计“经过某个点的所有方案”。由于只向右向下,所以统计经过点(i,j)的方案时,必须保证不经过(x,y),x<=i,y<=j的所有点。

    那么就按x排序再按y排序所有点,令f(i)表示到点i,不经过任何i左上方的点的方案数,则f(i)=S(Xi-1,Yi-1)-f(j)*S(Xi-Xj,Yi-Yj),其中Xj<=Xi,Yj<=Yi。先走合法方案到某个点,后面乱走到点i,这样统计方案一定不重复,因为f(j)表示的方案一定不含经过点k,Xk<=Xj,Yk<=Yj的方案,所以f(j)转移过来的方案都没经过他左上方的所有点,这样即使k的方案中可能有经过j,也不会重复。

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<stdlib.h>
     4 #include<algorithm>
     5 //#include<assert.h>
     6 //#include<iostream>
     7 using namespace std;
     8 
     9 int n,m,h;
    10 #define maxh 2011
    11 int f[maxh];
    12 struct Point
    13 {
    14     int x,y;
    15     bool operator < (const Point &b) const
    16     {return x<b.x || (x==b.x && y<b.y);}
    17 }a[maxh];
    18 #define maxn 200011
    19 int fac[maxn],inv[maxn];
    20 const int mod=1e9+7;
    21 int powmod(int a,int b)
    22 {
    23     int ans=1;
    24     for (;b;a=1ll*a*a%mod,b>>=1) if (b&1) ans=1ll*ans*a%mod;
    25     return ans;
    26 }
    27 void pre(int n)
    28 {
    29     fac[0]=1;for (int i=1;i<=n;i++) fac[i]=1ll*fac[i-1]*i%mod;
    30     inv[n]=powmod(fac[n],mod-2);for (int i=n-1;i>=0;i--) inv[i]=1ll*inv[i+1]*(i+1)%mod;
    31 }
    32 int C(int n,int m) {return 1ll*fac[n]*inv[n-m]%mod*inv[m]%mod;}
    33 int S(int n,int m) {return C(n+m,n);}
    34 int main()
    35 {
    36     scanf("%d%d%d",&n,&m,&h);
    37     for (int i=1;i<=h;i++) scanf("%d%d",&a[i].x,&a[i].y);
    38     sort(a+1,a+1+h);
    39     a[++h].x=n;a[h].y=m;
    40     pre(n+m+2);
    41     f[1]=S(a[1].x-1,a[1].y-1);
    42     for (int i=2;i<=h;i++)
    43     {
    44         f[i]=S(a[i].x-1,a[i].y-1);
    45         for (int j=1;j<i;j++)
    46             if (a[i].y>=a[j].y) f[i]-=1ll*f[j]*S(a[i].x-a[j].x,a[i].y-a[j].y)%mod,
    47             f[i]+=f[i]<0?mod:0;
    48     }
    49     printf("%d
    ",f[h]);
    50     return 0;
    51 }
    View Code
  • 相关阅读:
    5、axios获取后端数据
    token
    转载:requestAnimationFrame
    YII的特殊删除语句组装
    c /c++ 工程写法 linux makefile多文件编译 原理
    c 语言函数传参的sizeof问题
    使用mermaid语言定制甘特图,Typora/语雀都支持
    Nginx 配置文件
    Docker Compose(7)
    Docker网络模式详解及容器间网络通信(6)
  • 原文地址:https://www.cnblogs.com/Blue233333/p/7570650.html
Copyright © 2020-2023  润新知