思路很简单,期望逆序对最小肯定是按线段终点排序。
证:两个变量i,j
i是[li,ri] j是[lj,rj].
想要i尽量小于j,肯定是让i比j小的概率大于1/2.即i的中点小于j的中点
然后n^2枚举求期望即可。
不到半小时写出来过样例,但判断条件错了调了2h。。。。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod =998244353;
const int M =5000+7;
struct node
{
ll l,r,mid;
bool operator < (const node &b)const
{
return mid<b.mid;
}
}sg[M];
ll qpow(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1)ans=ans*a%mod;
a=a*a%mod;
b/=2;
}
return ans;
}
ll inv[M];
int main()
{
ll n,l,r;
scanf("%lld",&n);
for(int i=1;i<=n;i++)scanf("%lld%lld",&l,&r),sg[i]=node{l,r,l+r};
sort(sg+1,sg+1+n);
ll ans=0;
for(ll i=1;i<=n;i++)inv[i]=qpow(sg[i].r-sg[i].l+1,mod-2);
ll inv2=qpow(2,mod-2);
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
//让 i段 < j段 即形成一个逆序对 (后面的数小于前面的数)
{
// cout<<i<<" "<<j<<" "<<sg[i].l<<" "<<sg[i].r<<" - "<<sg[j].l<<" "<<sg[j].r<<endl;
ll li=sg[i].r-sg[i].l+1,lj=sg[j].r-sg[j].l+1,tp=0;
if(sg[i].r<=sg[j].l)tp=0;
else if(sg[i].l<=sg[j].l&&sg[i].r<=sg[j].r)//相交 i在左
{
// cout<<"-1111"<<endl;
ll lm=sg[i].r-sg[j].l+1;
tp=(lm-1)*lm%mod*inv2%mod;//一次函数,用中值代替这一段函数的值
}
else if(sg[i].l<=sg[j].l&&sg[i].r>=sg[j].r)//包含 i在外
{
// cout<<"-2222"<<endl;
tp=(lj-1)*lj%mod*inv2%mod;
tp=(tp+(sg[i].r-sg[j].r)*lj%mod)%mod;
}
else//包含 j在外
{
// cout<<"-3333"<<endl;
tp=(li-1)*li/2%mod;
tp=(tp+li*(sg[i].l-sg[j].l)%mod)%mod;
//tp=(sg[i].r-sg[j].l+sg[i].l-sg[j].l)*li%mod*inv2%mod;
}
// c/out<<tp<<" "<<li*lj<<endl;
ans=(ans+tp*inv[i]%mod*inv[j]%mod)%mod;
}
printf("%lld\n",ans);
return 0;
}