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;
    }
  • 相关阅读:
    [ Algorithm ] N次方算法 N Square 动态规划解决
    [ Algorithm ] LCS 算法 动态规划解决
    sql server全文索引使用中的小坑
    关于join时显示no join predicate的那点事
    使用scvmm 2012的动态优化管理群集资源
    附加数据库后无法创建发布,error 2812 解决
    浅谈Virtual Machine Manager(SCVMM 2012) cluster 过载状态检测算法
    windows 2012 r2下安装sharepoint 2013错误解决
    sql server 2012 数据引擎任务调度算法解析(下)
    sql server 2012 数据引擎任务调度算法解析(上)
  • 原文地址:https://www.cnblogs.com/rrsb/p/8660389.html
Copyright © 2011-2022 走看看