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;
    }
    
  • 相关阅读:
    一行代码搞定Dubbo接口调用
    测试周期内测试进度报告规范
    jq 一个强悍的json格式化查看工具
    浅析Docker容器的应用场景
    HDU 4432 Sum of divisors (水题,进制转换)
    HDU 4431 Mahjong (DFS,暴力枚举,剪枝)
    CodeForces 589B Layer Cake (暴力)
    CodeForces 589J Cleaner Robot (DFS,或BFS)
    CodeForces 589I Lottery (暴力,水题)
    CodeForces 589D Boulevard (数学,相遇)
  • 原文地址:https://www.cnblogs.com/wxjor/p/9540554.html
Copyright © 2011-2022 走看看