题意:给你两个给你一个n对整数的序列:(a1,b1),(a2,b2),…,(an,bn)。如果按第一个元素的非降序排序,
或者按第二个元素的非降序排序,则此序列称为坏序列。否则顺序是好的。输出有多少种排列方式使得这序列是好的。
思路:可以先求出坏序列有多少种,再用n!减去坏序列的种数即可,由于只要a,b其中一个为坏序列该序列就为坏序列,所以
坏序列的种数就等于a为坏序列的种数+b为坏序列的种数-a,b同时为坏序列的种数。
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<iostream> #include<queue> using namespace std; #define ll long long ll inf=998244353; struct node { ll x; ll y; }a[300005]; bool cmp(node xx,node yy) { if(xx.x==yy.x) return xx.y<yy.y; return xx.x<yy.x; } ll b[300005],c[300005]; ll fun(ll n) { ll s=1; for(ll i=2;i<=n;i++) s=(s*i)%inf; return s%inf; } int main() { ll n; while(~scanf("%lld",&n)) { for(ll i=1;i<=n;i++) { scanf("%lld %lld",&a[i].x,&a[i].y); b[i]=a[i].x; c[i]=a[i].y; } sort(b+1,b+n+1); sort(c+1,c+n+1); ll ans=1,sum=1,sum1=1,sum2=1; ll s=1,s1=1; for(ll i=2;i<=n;i++) { if(b[i]==b[i-1]) s++; else { sum=(sum*fun(s))%inf; s=1; } if(c[i]==c[i-1]) s1++; else { sum1=(sum1*fun(s1))%inf; s1=1; } } if(b[n]==b[n-1]) sum=(sum*fun(s))%inf; if(c[n]==c[n-1]) sum1=(sum1*fun(s1))%inf; sort(a+1,a+n+1,cmp); s=1; int v=1; for(ll i=2;i<=n;i++) { if(a[i].x==a[i-1].x&&a[i].y==a[i-1].y) s++; else { sum2=(sum2*fun(s))%inf; s=1; } if(a[i].y<a[i-1].y) { v=0; break; } } if(a[n].x==a[n-1].x&&a[n].y==a[n-1].y) sum2=(sum2*fun(s))%inf; if(v==0) sum2=0; sum=(sum1+sum+inf-sum2)%inf; ans=fun(n); ans=(ans+inf-sum)%inf; printf("%lld ",ans); } return 0; }