F. Good Contest
time limit per test 3 seconds
memory limit per test 256 megabytes
input standard input
output standard output
An online contest will soon be held on ForceCoders, a large competitive programming platform. The authors have prepared n problems; and since the platform is very popular, 998244351 coder from all over the world is going to solve them.
For each problem, the authors estimated the number of people who would solve it: for the i-th problem, the number of accepted solutions will be between and , inclusive.
The creator of ForceCoders uses different criteria to determine if the contest is good or bad. One of these criteria is the number of inversions in the problem order. An inversion is a pair of problems (x,y) such that x is located earlier in the contest (x<y), but the number of accepted solutions for y is strictly greater.
Obviously, both the creator of ForceCoders and the authors of the contest want the contest to be good. Now they want to calculate the probability that there will be no inversions in the problem order, assuming that for each problem i, any integral number of accepted solutions for it (between and ) is equally probable, and all these numbers are independent.
Input
The first line contains one integer — the number of problems in the contest.
Then n lines follow, the i-th line contains two integers and — the minimum and maximum number of accepted solutions for the i-th problem, respectively.
Output
The probability that there will be no inversions in the contest can be expressed as an irreducible fraction , where is coprime with 998244353. Print one integer — the value of , taken modulo 998244353, where is an integer such that .
Examples
input
3
1 2
1 2
1 2
output
499122177
input
2
42 1337
13 420
output
578894053
input
2
1 1
0 0
output
1
input
2
1 1
1 1
output
1
Note
The real answer in the first test is .
思路:比较简单的思路就是表示前个数满足条件时且第个数等于的方案数。但是题目给的数范围太大。
考虑到题目最多给50个区间,那么我们把题目所给数的区间离散化,那么最多可以得到100个区间,且每个数的范围区间是连续的。
因为题目要求递减,则可以用表示前个数用了第个及其后面的区间的方案数,那么答案就是。
现在的问题就是如何处理同一个区间存在多个数的情况以及要保证他们的大小满足题目要求。
转移如下:
即将区间里的数都放在第个区间,并用组合数选取个值(可重复)一一对应即可。
#include<bits/stdc++.h>
using namespace std;
const int MAX=2e5+10;
const int MOD=998244353;
typedef long long ll;
ll POW(ll x,ll n)
{
ll res=1;
while(n)
{
if(n&1)res=res*x%MOD;
x=x*x%MOD;
n/=2;
}
return res;
}
ll C(ll n,ll m)
{
if(m>n)return 0;
ll fz=1,fm=1;
for(ll i=n;i>=(n-m+1);i--)fz=fz*i%MOD;
for(ll i=1;i<=m;i++)fm=fm*i%MOD;
return fz*POW(fm,MOD-2)%MOD;
}
int L[51],R[51];
vector<ll>v;
void init(int n)
{
v.push_back(-1);
for(int i=1;i<=n;i++)
{
v.push_back(L[i]);
v.push_back(R[i]+1);
}
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
for(int i=1;i<=n;i++)
{
R[i]=lower_bound(v.begin(),v.end(),R[i]+1)-v.begin()-1;
L[i]=lower_bound(v.begin(),v.end(),L[i])-v.begin();
}
}
ll d[51][110];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)scanf("%d%d",&L[i],&R[i]);
init(n);
memset(d,0,sizeof d);
for(int i=0;i<v.size();i++)d[0][i]=1;
for(int i=1;i<=n;i++)
{
for(int j=L[i];j<=R[i];j++)
for(int k=i-1;k>=0;k--)
{
d[i][j]+=d[k][j+1]*C(v[j+1]-v[j]+i-k-1,i-k)%MOD;
d[i][j]%=MOD;
if(L[k]>j||R[k]<j)break;
}
for(int j=v.size()-1;j>=0;j--)(d[i][j]+=d[i][j+1])%=MOD;
}
ll ans=d[n][0];
for(int i=1;i<=n;i++)ans=ans*POW(v[R[i]+1]-v[L[i]],MOD-2)%MOD;
cout<<ans<<endl;
return 0;
}
纪念第一次变成