题目链接:https://codeforces.com/contest/1207/problem/D
思路:题目求的是保证两组数对是部分或全部递减序列,写就是说就是所有可能n! - 第一个数对不是递减序列的情况 - 第二个数对不是递减的情况 + 一二数对都不是递减的情况,(因为前两种情况算重复了)。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5e5 + 5;
vector <pair <ll , ll > > v;
ll f[maxn];
const ll mod = 998244353;
bool cmp1(pair <ll , ll> a , pair <ll , ll> b) {
return a.first < b.first;
}
bool cmp2(pair <ll , ll> a , pair <ll , ll> b) {
return a.second < b.second;
}
bool cmp3(pair <ll , ll> a , pair <ll , ll> b) {
return (a.first < b.first || (a.first == b.first && a.second < b.second));
}
int main() {
int n;
ios::sync_with_stdio(0);
cin >> n ;
for(int i = 0 ; i < n ; i++) {
ll a , b;
cin >> a >> b;
v.push_back(make_pair(a,b));
}
sort(v.begin() , v.end() , cmp1);
ll a = 1 , b = 1, c = 1;
f[1] = 1;
for(int i = 2 ; i <= n ; i++) {
f[i] = (f[i - 1] * i) % mod;
}
for(int i = 0 ; i < v.size() ;i++ ) {
ll t = v[i].first , cnt = 0;
while(i < v.size() && v[i].first == t ) {
cnt++;
i++;
}
i--;
a = (a * f[cnt]) % mod;
}
ll ans = f[n];
ans = (ans + (mod - a)) % mod;
sort(v.begin() , v.end() , cmp2);
for(int i = 0 ; i < v.size() ; i++) {
ll t = v[i].second , cnt = 0;
while(i < v.size() && v[i].second == t) {
cnt++;
i++;
}
i--;
b = (b * f[cnt]) % mod;
}
ans = (ans + (mod - b)) % mod;
sort(v.begin() , v.end() , cmp3);
ll cnt = 1;
for(int i = 1 ; i < v.size() ; i++) {
if(v[i].second < v[i - 1].second) {
c = 0;
break;
}
if(v[i].first == v[i - 1].first && v[i].second == v[i - 1].second) {
cnt++;
}
else {
c = (c * f[cnt]) % mod;
cnt = 1;
}
}
if(cnt > 1)c = (c * f[cnt]) % mod;
ans = (ans + c) % mod;
cout << ans << "\n";
return 0;
}