zoukankan      html  css  js  c++  java
  • NOI 十连测 Round 5 T2 运河计划

    SOL:

      不难发现,第二维坐标最小的红点一定对应第二维坐标最小的蓝 点,次小的、第三小的……均一一对应,否则线路必然会有交叉或者 根本无法修建。

      下面我们讨论在给定一对红蓝点之间有多少条线路。 (1)不存在障碍点,显然条数为 C(Δx + Δy, Δx),Δx、Δy 分别为第 一、二维坐标差值; (2)存在障碍点,由于整张图是有向无环图,我们可以把红点、 蓝点及它们构成的矩形框中存在的紫点拓扑排序。记 F[i]表示从红点 到第 i 个关键点(可能是紫点或蓝点),中间不经过紫点的方案数, 这可以应用容斥 O(q2 )的解决。 对每对红蓝点间均应用上述过程,即得一个 O(pq2 )的算法解决不 考虑交叉的问题。

      我们可以容斥上面的柿子,写出来震惊地发现是行列式。那么就过了。

    #include<bits/stdc++.h>
    #define mo 998244353
    #define LL long long
    #define N 200007
    #define SIZ 2007
    #define sight(c) ('0'<=c&&c<='9')
    inline void read(int &x){
        static char c;
        for (c=getchar();!sight(c);c=getchar());
        for (x=0;sight(c);c=getchar())x=x*10+c-48;
    }
    void write(int x){if (x<10) {putchar('0'+x); return;} write(x/10); putchar('0'+x%10);}
    inline void writeln(int x){ if (x<0) putchar('-'),x*=-1; write(x); putchar('
    '); }
    inline void writel(int x){ if (x<0) putchar('-'),x*=-1; write(x); putchar(' '); }
    using namespace std;
    struct Node{
        int x,y,to;
        inline bool operator <(const Node &A)const{
           return x==A.x?y<A.y:x<A.x;
        }
    }g[SIZ];
    LL fac[N],ni[N],ans[SIZ],pp;
    inline LL c(int x,int y){
      return (fac[x]*ni[y]%mo)*ni[x-y]%mo;
    }
    LL qsm(LL x,LL y){
        static LL anw;
        for (anw=1;y;y>>=1,x=x*x%mo) if (y&1) anw=anw*x%mo;
        return anw;
    }
    void sol(LL* anw,int x){
        memset(ans,0,sizeof ans);
        for (int i=1;i<=pp;i++) if (g[i].y>=x){
            ans[i]=c(g[i].x+g[i].y-x,g[i].x);
            for (int j=1;j<i;j++) 
              if ((g[j].to==0)&&g[j].y>=x&&g[j].x<=g[i].x&&g[j].y<=g[i].y)
                ans[i]=(ans[i]-ans[j]*c(g[i].x+g[i].y-g[j].x-g[j].y,g[i].y-g[j].y)%mo)%mo,
                ans[i]=(ans[i]+mo)%mo;
            if (g[i].to) anw[g[i].to]=ans[i];
        }
    }
    void per(){
        fac[0]=1;
        for (int i=1;i<N;i++) fac[i]=fac[i-1]*i%mo;
        ni[N-1]=qsm(fac[N-1],mo-2);
        for (int i=N-1;i;i--) ni[i-1]=ni[i]*i%mo;
    }
    LL ANS=1,t;int p,q,n,m,a[SIZ],b[SIZ];
    LL f[SIZ][SIZ];
    void doniv(){
        for (int i=1;i<=p;i++) 
         for (int j=i+1;j<=p;j++)
            while (f[j][i]){
                t=f[i][i]/f[j][i];
                for (int z=i;z<=p;z++){
                    f[i][z]=(f[i][z]-f[j][z]*t)%mo;
                    if (f[i][z]<0) f[i][z]+=mo;
                    swap(f[i][z],f[j][z]);
                }
                ANS*=-1;
            }
        for (int i=1;i<=p;i++) ANS=ANS*f[i][i]%mo;
        ANS=(ANS+mo)%mo;
    }
    signed main () {
        freopen("canal.in","r",stdin);
        freopen("canal.out","w",stdout);
        read(n); read(m); read(p); read(q);
        per();
        for (int i=1;i<=p;i++)  read(a[i]);
        for (int i=1;i<=p;i++)  read(b[i]);
        sort(a+1,a+p+1); sort(b+1,b+p+1);
        for (int i=1;i<=q;i++) read(g[i].x),read(g[i].y);
        for (int i=1;i<=p;i++) g[i+q].x=n,g[i+q].y=b[i],g[i+q].to=i;
        sort(g+1,g+q+p+1); 
        pp=q+p;
        for (int i=1;i<=p;i++)  sol(f[i],a[i]);
    //    for (int i=1;i<=p;i++,putchar('
    '))
    //     for (int j=1;j<=p;j++) writel(f[i][j]);
        doniv();
    //    for (int i=1;i<=p;i++,putchar('
    '))
    //     for (int j=1;j<=p;j++) writel(f[i][j]);
        writeln(ANS); 
        return 0;
    }
  • 相关阅读:
    JavaScript高级程序设计-(3) 变量、作用域和内存问题
    JavaScript高级程序设计-(2)基础概念
    JavaScript高级程序设计-(1)html中使用JavaScript
    ASP.NET 一句代码实现批量数据绑定
    C#改善程序的50种方法
    ASP.NET探讨:技术的学习顺序问题
    docker 操作命令
    友盟分享 | 移动大数据平台架构思想以及实践经验
    [MapReduce_3] MapReduce 程序运行流程解析
    [MapReduce_add_3] MapReduce 通过分区解决数据倾斜
  • 原文地址:https://www.cnblogs.com/rrsb/p/8660389.html
Copyright © 2011-2022 走看看