zoukankan      html  css  js  c++  java
  • BZOJ4767 两双手

    Link
    首先我们可以列方程解出到某个点两种移动方式分别要走多少次。
    那么这个就是经典的走路问题,答案为(x+ychoose x)
    然后我们给所有的点排个序,设(f_i)表示不经过其它([1,i))的点到达这个点的方案数。
    转移的话容斥就行,枚举一个不经过的点(j),记从(j)(i)的方案数为(s)(f_i-=s*f_j)

    #include<bits/stdc++.h>
    #define pi pair<int,int>
    #define fi first
    #define se second
    using namespace std;
    const int N=507,lim=500000,P=1000000007;
    int read(){int x;cin>>x;return x;}
    int dec(int a,int b){a-=b;return a<0? a+P:a;}
    int mul(int a,int b){return 1ll*a*b%P;}
    int inv(int a){int r=1,k=P-2;for(;k;k>>=1,a=mul(a,a))if(k&1)r=mul(a,r);return r;}
    int ax,ay,bx,by,ex,ey,n,fac[lim+7],ifac[lim+7],f[N];pi a[N];
    void cal(int &x,int &y)
    {
        int a=x*by-y*bx,b=x*ay-y*ax,d=ax*by-ay*bx;
        if(!d||a/d*d!=a||b/d*d!=b) return (void)(x=y=-1);
        x=a/d,y=-b/d;
    }
    int C(int n,int m){return mul(mul(fac[n],ifac[m]),ifac[n-m]);}
    int num(int x,int y){return x<0||0>y? 0:C(x+y,x);}
    int main()
    {
        int i,j,x,y;
        ex=read(),ey=read(),n=read(),ax=read(),ay=read(),bx=read(),by=read(),cal(ex,ey);
        for(i=1;i<=n;++i)
        {
    	x=read(),y=read(),cal(x,y);
    	if(x<0||x>ey||y<0||y>ey) --i,--n; else a[i]=pi(x,y);
        }
        a[++n]=pi(ex,ey),sort(a+1,a+n+1),fac[0]=1;
        for(i=1;i<=lim;++i) fac[i]=mul(fac[i-1],i);
        for(ifac[lim]=inv(fac[lim]),i=lim;i;--i) ifac[i-1]=mul(ifac[i],i);
        for(i=1;i<=n;++i) for(f[i]=num(a[i].fi,a[i].se),j=1;j<i;++j) f[i]=dec(f[i],mul(f[j],num(a[i].fi-a[j].fi,a[i].se-a[j].se)));
        cout<<f[n];
    }
    
  • 相关阅读:
    对象解析
    git 入门教程之分支策略
    git 入门教程之冲突合并
    git 入门教程之分支总览
    git 入门教程之分支管理
    git 入门教程之远程仓库
    git 入门教程之删除文件
    git 入门教程之撤销更改
    git 入门教程之版本控制
    git 入门教程之基本概念
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/11724981.html
Copyright © 2011-2022 走看看