zoukankan      html  css  js  c++  java
  • [BZOJ3782] 上学路线

    [BZOJ3782] 上学路线

    Description

    小C所在的城市的道路构成了一个方形网格,它的西南角为(0,0),东北角为(N,M)。小C家住在西南角,学校在东北角。现在有T个路口进行施工,小C不能通过这些路口。小C喜欢走最短的路径到达目的地,因此他每天上学时都只会向东或北行走;而小C又喜欢走不同的路径,因此他问你按照他走最短路径的规则,他可以选择的不同的上学路线有多少条。由于答案可能很大,所以小C只需要让你求出路径数mod P的值。

    Input

    第一行,四个整数N、M、T、P。接下来的T行,每行两个整数,表示施工的路口的坐标。

    Output

    一行,一个整数,路径数mod P的值。

    Sample Input

    3 4 3 1019663265
    3 0
    1 1
    2 2

    Sample Output

    8

    HINT

    1<=N,M<=10^10
    0<=T<=200
    p=1000003或p=1019663265

    试题分析

    显然求补集更加方便,于是求总方案数-不合法方案数。
    不合法的方案定然会经过某一个坏点,所以求出(g_i)表示从起点到第(i)个坏点途中不经过任何坏点的方案数。
    那么就是总数-经过其中坏点的方案数。
    为了方便,把最后一个点也视作坏点dp就可以了。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    //#include<cmath>
    #include<algorithm>
     
    using namespace std;
    #define LL long long
    inline LL read(){
        LL x=0,f=1; char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const LL INF = 2147483600;
    const LL MAXN = 1000100;
     
    LL f[MAXN+1];
    LL N,M,T,P; LL Mod;
     
    struct poi{LL x,y;}p[MAXN+1];
    bool cmp(poi a,poi b){if(a.x!=b.x) return a.x<b.x; return a.y<b.y;}
    LL fac[MAXN+1],ifac[MAXN+1],inv[MAXN+1];
     
    inline LL C(LL n,LL m){
        if(n<m) return 0; if(!m) return 1;
        if(n<Mod&&m<Mod) return fac[n]*ifac[m]%Mod*ifac[n-m];
        return C(n%Mod,m%Mod)*C(n/Mod,m/Mod)%Mod;
    }
    inline void init(){
        ifac[0]=fac[0]=1; inv[1]=1; memset(f,0,sizeof(f));
        for(LL i=2;i<Mod;i++) inv[i]=(Mod-(Mod/i)*inv[Mod%i]%Mod)%Mod;
        for(LL i=1;i<Mod;i++) ifac[i]=ifac[i-1]*inv[i]%Mod;
        for(LL i=1;i<Mod;i++) fac[i]=fac[i-1]*i%Mod; return ;
    }
    inline LL calc(){
        init();
        for(LL i=1;i<=T;i++){
            f[i]=0;
            for(LL j=1;j<i;j++){
                if(p[j].x<=p[i].x&&p[j].y<=p[i].y){
                    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; 
                } 
            }
            f[i]=(C(p[i].x+p[i].y,p[i].x)-f[i]+Mod)%Mod; //cout<<i<<":"<<p[i].x<<" "<<p[i].y<<"  :"<<f[i]<<endl;
        } return f[T];
    }
    inline void exgcd(LL a,LL b,LL &x,LL &y){
        if(!b){x=1; y=0; return ;} exgcd(b,a%b,x,y);
        LL tmp=x; x=y; y=tmp-a/b*x; return ;
    }
    inline LL Get(LL a,LL c,LL b){
        LL x,y; exgcd(a,b,x,y); x=(x+b)%b;
        return x*a%P*c%P;
    }
     
    int main(){
        //freopen(".in","r",stdin);
        //freopen(".out","w",stdout);
        N=read(),M=read(),T=read(),P=read();
        for(LL i=1;i<=T;i++){
            p[i].x=read(),p[i].y=read();
        } sort(p+1,p+T+1,cmp); p[++T].x=N; p[T].y=M;
        if(P==1000003){
            Mod=P; printf("%lld
    ",calc()); return 0;
        } LL a1,a2,a3,a4,ans=0;
        Mod=3; a1=calc(); Mod=5; a2=calc();
        Mod=6793; a3=calc(); Mod=10007; a4=calc();
        ans=(((ans+Get(P/3,a1,3))%P+Get(P/5,a2,5))%P+Get(P/6793,a3,6793))%P+Get(P/10007,a4,10007);
        ans%=P; printf("%lld
    ",ans%P);
        return 0;
    }
    
  • 相关阅读:
    UVA 10618 Tango Tango Insurrection
    UVA 10118 Free Candies
    HDU 1024 Max Sum Plus Plus
    POJ 1984 Navigation Nightmare
    CODEVS 3546 矩阵链乘法
    UVA 1625 Color Length
    UVA 1347 Tour
    UVA 437 The Tower of Babylon
    UVA 1622 Robot
    UVA127-"Accordian" Patience(模拟)
  • 原文地址:https://www.cnblogs.com/wxjor/p/9540554.html
Copyright © 2011-2022 走看看