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;
}
紀念第一次變成