zoukankan      html  css  js  c++  java
  • BZOJ 4767: 两双手

    犯了个睿智错误调了30min真是吃**了

    首先由于(Ax imes By-Ay imes Bx ot =0),那么我们显然可以把两种走法看作基底,每个点都可以表示成两种走法的次数的有序数对

    显然这种表示法是唯一的(如果存在的话)

    那么原来的问题其实就变成一般的坐标系上走路了,只能向上和向右,不能经过障碍点

    然后这个题好像暑假在CX考过,所以才会做的说,我们考虑先把所有关键点(包括终点)按(x)排序,这样只能从前面的点走到后面的点而不能走回头

    (f_i)表示走到(i)点不经过(i)之前的关键点的方案数,(g_{i,j})表示从(i)走到(j)不考虑任何因素的方案数,显然(g_{i,j}=C_{x_j-x_i+y_j-y_i}^{x_j-x_i})

    那么我们有:

    [f_{i}=g_{0,i}-sum_{j=1}^{i-1} g_{j,i} imes f_j ]

    不经过的方案=所有方案-必定经过的方案,一个套路的容斥

    这也启示我们有的时候我们可以通过定下顺序使得传统的容斥复杂度骤降,也算是一种常用套路吧

    #include<cstdio>
    #include<algorithm>
    #define RI register int
    #define CI const int&
    using namespace std;
    const int N=505,mod=1e9+7,S=500000;
    int Ax,Ay,Bx,By;
    struct data
    {
        int x,y;
        inline bool trans(void)
        {
            int a1=By*x-Bx*y,a2=Ax*By-Ay*Bx,b1=Ay*x-Ax*y,b2=Bx*Ay-Ax*By;
            if (a2==0||b2==0) return 0; if ((a1/a2)*a2!=a1) return 0;
            if ((b1/b2)*b2!=b1) return 0; x=a1/a2; y=b1/b2; return 1;   
        }
        friend inline bool operator < (const data& A,const data& B)
        {
            return A.x==B.x?A.y<B.y:A.x<B.x;
        }
    }a[N],p,tar; int n,fact[S+5],inv[S+5],f[N];
    inline void dec(int& x,CI y)
    {
        if ((x-=y)<0) x+=mod;
    }
    inline int quick_pow(int x,int p=mod-2,int mul=1)
    {
        for (;p;p>>=1,x=1LL*x*x%mod) if (p&1) mul=1LL*mul*x%mod; return mul;
    }
    inline void init(CI n)
    {
        RI i; for (fact[0]=i=1;i<=n;++i) fact[i]=1LL*fact[i-1]*i%mod;
        for (inv[n]=quick_pow(fact[n]),i=n-1;~i;--i) inv[i]=1LL*inv[i+1]*(i+1)%mod;
    }
    inline int C(CI n,CI m)
    {
        if (n<m) return 0; return 1LL*fact[n]*inv[m]%mod*inv[n-m]%mod;
    }
    int main()
    {
        RI i,j; scanf("%d%d%d%d%d%d%d",&tar.x,&tar.y,&n,&Ax,&Ay,&Bx,&By); 
        if (!tar.trans()) return puts("0"),0; for (i=1;i<=n;++i)
        {
            scanf("%d%d",&a[i].x,&a[i].y);
            if (!a[i].trans()||a[i].x>tar.x||a[i].y>tar.y) --i,--n;
        }
        for (a[++n]=tar,init(S),sort(a+1,a+n+1),i=1;i<=n;++i)
        for (f[i]=C(a[i].x+a[i].y,a[i].x),j=1;j<i;++j)
        dec(f[i],1LL*C(a[i].x-a[j].x+a[i].y-a[j].y,a[i].x-a[j].x)*f[j]%mod);
        return printf("%d",f[n]),0;
    }
    
  • 相关阅读:
    python : 将txt文件中的数据读为numpy数组或列表
    ROS :为IDE配置环境变量
    ROS 教程之 navigation :在 catkin 环境下创建costmap layer plugin
    ROS 教程之 vision : 用各种摄像头获取图像
    ROS 教程之 network:多台计算机之间网络通信(2)
    MS sql 查询动态表名的方法
    把ocx打包成CAB,并签名
    DataSet 转换成List
    C# 反序列化datetime的处理
    PSP软件开发过程管理
  • 原文地址:https://www.cnblogs.com/cjjsb/p/12253182.html
Copyright © 2011-2022 走看看