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('\n'); }
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('\n'))
//     for (int j=1;j<=p;j++) writel(f[i][j]);
    doniv();
//    for (int i=1;i<=p;i++,putchar('\n'))
//     for (int j=1;j<=p;j++) writel(f[i][j]);
    writeln(ANS); 
    return 0;
}

 

转载于:https://www.cnblogs.com/rrsb/p/8660389.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本火锅店点餐系统采用Java语言和Vue技术,框架采用SSM,搭配Mysql数据库,运行在Idea里,采用小程序模式。本火锅店点餐系统提供管理员、用户两种角色的服务。总的功能包括菜品的查询、菜品的购买、餐桌预定和订单管理。本系统可以帮助管理员更新菜品信息和管理订单信息,帮助用户实现在线的点餐方式,并可以实现餐桌预定。本系统采用成熟技术开发可以完成点餐管理的相关工作。 本系统的功能围绕用户、管理员两种权限设计。根据不同权限的不同需求设计出更符合用户要求的功能。本系统中管理员主要负责审核管理用户,发布分享新的菜品,审核用户的订餐信息和餐桌预定信息等,用户可以对需要的菜品进行购买、预定餐桌等。用户可以管理个人资料、查询菜品、在线点餐和预定餐桌、管理订单等,用户的个人资料是由管理员添加用户资料时产生,用户的订单内容由用户在购买菜品时产生,用户预定信息由用户在预定餐桌操作时产生。 本系统的功能设计为管理员、用户两部分。管理员为菜品管理、菜品分类管理、用户管理、订单管理等,用户的功能为查询菜品,在线点餐、预定餐桌、管理个人信息等。 管理员负责用户信息的删除和管理,用户的姓名和手机号都可以由管理员在此功能里看到。管理员可以对菜品的信息进行管理、审核。本功能可以实现菜品的定时更新和审核管理。本功能包括查询餐桌,也可以发布新的餐桌信息。管理员可以查询已预定的餐桌,并进行审核。管理员可以管理公告和系统的轮播图,可以安排活动。管理员可以对个人的资料进行修改和管理,管理员还可以在本功能里修改密码。管理员可以查询用户的订单,并完成菜品的安排。 当用户登录进系统后可以修改自己的资料,可以使自己信息的保持正确性。还可以修改密码。用户可以浏览所有的菜品,可以查看详细的菜品内容,也可以进行菜品的点餐。在本功能里用户可以进行点餐。用户可以浏览没有预定出去的餐桌,选择合适的餐桌可以进行预定。用户可以管理购物车里的菜品。用户可以管理自己的订单,在订单管理界面里也可以进行查询操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值