ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

http://uoj.ac/problem/209

当x!=y时,这个限制条件是确定的,可以枚举总通过数,用组合数计算,当x==y时,这个限制条件表示前x个全部通过或后x个全部通过,只有最大的x有用,可以用容斥计算。

#include<bits/stdc++.h>
const int P=998244353;
int T,n,m,pp[3],C[5007][5007];
struct pos{
    int x,y,t;
    bool operator<(pos p)const{return x<p.x;}
}ps[3][1077];
void ins(pos p){
    for(int i=0;i<3;++i)ps[i][pp[i]++]=p;
}
int cal(int w,int m){
    pos*a=ps[w];
    int ap=pp[w],s=1;
    for(int i=1;i<ap;++i){
        int v1=a[i].x-a[i-1].x,v2=a[i].y-a[i-1].y+(a[i].t-a[i-1].t)*m;
        if(v2<0||v2>v1)return 0;
        s=1ll*s*C[v1][v2]%P;
    }
    return s;
}
int main(){
    C[0][0]=1;
    for(int i=0;i<5000;++i){
        for(int j=0;j<=i;++j){
            (C[i+1][j]+=C[i][j])%=P;
            (C[i+1][j+1]+=C[i][j])%=P;
        }
    }
    for(scanf("%d",&T);T;--T){
        scanf("%d%d",&n,&m);
        int mx=-1;
        pp[0]=pp[1]=pp[2]=0;
        ins((pos){0,0,0});
        ins((pos){n,0,1});
        for(int i=0,a,b;i<m;++i){
            scanf("%d%d",&a,&b);
            if(a>b)ins((pos){a,b,0});
            else if(a<b)ins((pos){n-b,-a,1});
            else{
                if(a>mx)mx=a;
            }
        }
        if(~mx){
            ps[0][pp[0]++]=(pos){n-mx,-mx,1};
            ps[1][pp[1]++]=(pos){mx,mx,0};
            ps[2][pp[2]++]=(pos){mx,mx,0};
            ps[2][pp[2]++]=(pos){n-mx,-mx,1};
        }
        for(int i=0;i<3;++i)std::sort(ps[i],ps[i]+pp[i]);
        int ans=0;
        for(int i=0;i<=n;++i){
            int sgn[]={1,1,-1};
            for(int j=0;j<3;++j){
                ans=(ans+cal(j,i)*sgn[j])%P;
            }
        }
        printf("%d\n",(ans+P)%P);
    }
    return 0;
}

 

posted on 2017-09-16 08:19  nul  阅读(148)  评论(0编辑  收藏  举报