1207D Number Of Permutations

题目大意

给你n个二元组

问你有几种排列是的按两个关键字中的任意一个都不是不降排列的

分析

不妨容斥

我们先加上总的方案数$n!$

之后我们按第一个关键字排序

因为值相同的情况下不影响答案

所以让总方案数减去$\prod sum_{ai}!$即可

对于第二关键字的情况同上

我们再使序列同时按照第一关键字和第二关键字排序

然后总方案数加上$\prod sum_{(ai,bi)}!$即可

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
#define int long long
const int mod = 998244353;
int p[300100],n,m,Ans;
struct node {
    int x,y;
};
node d[300100];
inline void init(){
    int i,j,k;
    p[0]=1;
    for(i=1;i<=n;i++)p[i]=p[i-1]*i%mod;
}
inline bool cmp1(const node a,const node b){
    if(a.x==b.x)return a.y<b.y;
    return a.x<b.x;
} 
inline bool cmp2(const node a,const node b){
    return a.y<b.y;
} 
signed main(){
    int i,j,k;
    scanf("%lld",&n);
    init();
    for(i=1;i<=n;i++)scanf("%lld%lld",&d[i].x,&d[i].y);
    Ans=p[n];
    sort(d+1,d+n+1,cmp1);
    int res=1; 
    for(i=1;i<=n;i++){
      j=i;
      while(j+1<=n&&d[j+1].x==d[j].x)j++;
      res=res*p[j-i+1]%mod;
      i=j;
    }
    Ans=(Ans-res+mod)%mod;
    sort(d+1,d+n+1,cmp2);
    res=1; 
    for(i=1;i<=n;i++){
      j=i;
      while(j+1<=n&&d[j+1].y==d[j].y)j++;
      res=res*p[j-i+1]%mod;
      i=j;
    }
    Ans=(Ans-res+mod)%mod;
    sort(d+1,d+n+1,cmp1);
    int ok=1;
    for(i=2;i<=n;i++)
      if(d[i].y<d[i-1].y){
          ok=0;
          break;
      }
    res=1;
    if(ok){
      for(i=1;i<=n;i++){
        j=i;
        while(j+1<=n&&d[j+1].y==d[j].y&&d[j+1].x==d[j].x)j++;
        res=res*p[j-i+1]%mod;
        i=j;
      }
      Ans=(Ans+res)%mod;
    } 
    cout<<Ans<<"\n";
    return 0;
}
posted @ 2019-08-26 21:41  水题收割者  阅读(207)  评论(0编辑  收藏  举报