zoukankan      html  css  js  c++  java
  • BJWC2018上学路线

    题目描述

    小B 所在的城市的道路构成了一个方形网格,它的西南角为(0,0),东北角为(N,M)。

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

    输入输出格式

    输入格式:
    第一行为四个整数N、M、T、P。

    接下来的T 行,每行两个整数,表示施工的路口的坐标。

    输出格式:
    一行一个整数,表示路径数mod P 的值。

    此题涉及到的数论知识有很多:扩展欧几里得算法、卢卡斯定理(组合数)、中国剩余定理(合并)。
    当没有施工点时,答案即C(n+m,m)。
    当有施工点时,考虑到j点能影响到i点当且仅当x[i]>=x[j]且y[i]>=y[j]时。影响的路径条数为f[i]=f[i]-f[j]*C(a[i].x-a[j].x+a[i].y-a[j].y,a[i].x-a[j].x),它的解释为:到j点的路径条数乘上j点到i点的路径条数。我们把所有符合条件的j都减去(思考一下这样为什么不会重复减去)。计算之前先sort一遍就可以了,对于取模,卢卡斯定理计算就好了。
    但模数不是质数的情况,中国剩余定理合并即可。

    Code

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    long long mod,n,m,t,p,jie[1000009],ni[1000009],f[209],x,y,a1,a2,a3,a4,ans;
    struct fe
    {
        long long x,y;
    }a[209];
    bool cmp(fe a,fe b)
    {
        return(a.x==b.x)?(a.y<b.y):(a.x<b.x);
    }
    long long lucas(long long n,long long m)
    {
        if(m>n)return 0;
        if(!m)return 1;
        if(n<mod)return jie[n]*ni[m]*ni[n-m]%mod;
        return lucas(n%mod,m%mod)*lucas(n/mod,m/mod)%mod;
    }
    void exgcd(long long a,long long b)
    {
        if(!b)
        {
            x=1;
            y=0;
            return;
        }
        exgcd(b,a%b);
        long long k=x;
        x=y;
        y=k-a/b*y;
    }
    long long work1()
    {
        memset(f,0,sizeof(f));
        ni[0]=ni[1]=1;
        jie[1]=1;
        for(int i=2;i<=mod;++i)
        {
         jie[i]=(jie[i-1]*i)%mod;
         ni[i]=(mod-mod/i)*ni[mod%i]%mod;
        }
        for(int i=2;i<=mod;++i)
          ni[i]=ni[i]*ni[i-1]%mod;
        for(int i=1;i<=t;++i)
          {
           f[i]=lucas(a[i].x+a[i].y,a[i].x)%mod;
           for(int j=1;j<i;++j)
             if(a[i].x>=a[j].x&&a[i].y>=a[j].y)f[i]=(f[i]-f[j]*lucas(a[i].x-a[j].x+a[i].y-a[j].y,a[i].x-a[j].x)%mod+mod)%mod;
          }
        return f[t];
    }
    long long bing(long long a,long long b,long long c)
    {
        x=0;y=0;
        exgcd(a,c);
        x=(x+c)%c;
        return x*a%p*b%p;
    }
    int main()
    {
        cin>>n>>m>>t>>p;
        for(int i=1;i<=t;++i)scanf("%lld%lld",&a[i].x,&a[i].y);
        a[++t].x=n,a[t].y=m;
        sort(a+1,a+t+1,cmp);
        if(p==1000003)
        {
            mod=p;
            cout<<work1();
        }
        else
        {
            mod=3;a1=work1();
            mod=5;a2=work1();
            mod=6793;a3=work1();
            mod=10007;a4=work1();
            ans=(ans+bing(p/3,a1,3))%p;//cout<<ans;
            ans=(ans+bing(p/5,a2,5))%p;//<<ans;
            ans=(ans+bing(p/6793,a3,6793))%p;//cout<<ans;
            ans=(ans+bing(p/10007,a4,10007))%p;//cout<<ans;
            cout<<ans;
        }
        return 0;
    } 


  • 相关阅读:
    合并表已经转化对象的操作
    终于也有自己的博客园一角了,权当新人报到帖了
    常见软件滤波器总结
    按键设计总结
    关于goto语句
    Delphi XE2 Default Keyboard Shortcuts
    Delphi XE2 IDE Classic Keyboard Shortcuts
    Delphi实现静态变量
    datasnap传输流/文件问题
    查询条件的封装(小结)
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/9389204.html
Copyright © 2011-2022 走看看