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;
    }
    
  • 相关阅读:
    【Mocha.js 101】Mocha 入门指南
    CSS 中 Font-Family 中英文对照表
    Android Studio中找出不再使用的资源
    Java反射机制实战——字段篇
    python进阶——day02、03面向对象进阶
    python进阶_day01面对对象编程基础
    day05(文件配置命令和远程登录)
    day04(磁盘管理与目录介绍)
    day03(系统启动及常用的Linux命令的基本使用)
    day02(操作系统简介和Linux的安装与常用命令简介)
  • 原文地址:https://www.cnblogs.com/wxjor/p/9540554.html
Copyright © 2011-2022 走看看