zoukankan      html  css  js  c++  java
  • [BZOJ 4767]两双手(组合数学+Dp)

    Description

    老W是个棋艺高超的棋手,他最喜欢的棋子是马,更具体地,他更加喜欢马所行走的方式。老W下棋时觉得无聊,便
    决定加强马所行走的方式,更具体地,他有两双手,其中一双手能让马从(u,v)移动到(u+Ax,v+Ay)而另一双手能让
    马从(u,v)移动到(u+Bx,v+By)。小W看见老W的下棋方式,觉得非常有趣,他开始思考一个问题:假设棋盘是个无限
    大的二维平面,一开始马在原点(0,0)上,若用老W的两种方式进行移动,他有多少种不同的移动方法到达点(Ex,Ey
    )呢?两种移动方法不同当且仅当移动步数不同或某一步所到达的点不同。老W听了这个问题,觉得还不够有趣,他
    在平面上又设立了n个禁止点,表示马不能走到这些点上,现在他们想知道,这种情况下马有多少种不同的移动方
    法呢?答案数可能很大,你只要告诉他们答案模(10^9+7)的值就行。

    Solution

    Ax*By-Ay*Bx≠0所以向量A、B的步数是固定的,走法也就有C(m+n,m)种

    先对障碍点排序

    Dp,f[i]表示到达障碍点i且不经过其他障碍点的方案数(用容斥减去经过其他障碍点的方案数)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #define Mod 1000000007
    #define MAXN 500005
    typedef long long LL;
    using namespace std;
    int n,ax,ay,bx,by;
    LL fac[MAXN],inv[MAXN],f[MAXN];
    struct Node
    {
        int x,y;
    }p[MAXN];
    void init()
    {
        fac[0]=1,inv[1]=1;
        for(int i=1;i<MAXN;i++)
        fac[i]=(fac[i-1]*i)%Mod;
        for(int i=2;i<MAXN;i++)
        inv[i]=((Mod-Mod/i)*inv[Mod%i])%Mod;
        inv[0]=1;
        for(int i=1;i<=MAXN;i++)
        inv[i]=(inv[i]*inv[i-1])%Mod;
    }
    LL C(LL x,LL y)
    {
        if(x<y)return 0;
        return ((fac[x]*inv[y])%Mod*inv[x-y])%Mod;
    }
    bool cmp(Node A,Node B)
    {
        if(A.x==B.x)return A.y<B.y;
        return A.x<B.x; 
    }
    void calc(int &x,int &y)
    {
        int m,n;
        if((ay*x-ax*y)%(bx*ay-ax*by)){x=-1,y=-1;return;}
        n=(ay*x-ax*y)/(bx*ay-ax*by);
        if((by*x-bx*y)%(ax*by-bx*ay)){x=-1,y=-1;return;}
        m=(by*x-bx*y)/(ax*by-bx*ay);
        x=m,y=n;
    }
    int main()
    {
        init();
        scanf("%d%d%d",&p[0].x,&p[0].y,&n);
        scanf("%d%d%d%d",&ax,&ay,&bx,&by);
        calc(p[0].x,p[0].y);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&p[i].x,&p[i].y);
            calc(p[i].x,p[i].y);
        }
        sort(p+1,p+1+n,cmp);
        p[n+1]=p[0];
        for(int i=1;i<=n+1;i++)
        {
            if(p[i].x==-1)continue; 
            f[i]=C(p[i].x+p[i].y,p[i].x);
            for(int j=1;j<i;j++)
            f[i]=(f[i]-f[j]*C(p[i].x-p[j].x+p[i].y-p[j].y,p[i].x-p[j].x)%Mod+Mod)%Mod;
        }
        printf("%lld
    ",f[n+1]);
        return 0;
    }
  • 相关阅读:
    angular4-http
    angular4-表单
    angular4-事件绑定
    angular4-常用指令
    angular4-自定义组件
    sea.js与require.js的区别
    OC面向对象下之协议
    OC基本程序和面向对象
    OC面对对象下之类别
    Foudation框架之字典
  • 原文地址:https://www.cnblogs.com/Zars19/p/6823051.html
Copyright © 2011-2022 走看看