Codeforces-1259F:Good Contest(DP)

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 lil_i and rir_i, 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 lil_i and rir_i) is equally probable, and all these numbers are independent.

Input
The first line contains one integer n(2n50)n (2≤n≤50) — the number of problems in the contest.

Then n lines follow, the i-th line contains two integers lil_i and rir_i (0liri998244351)(0≤l_i≤r_i≤998244351) — 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 xy\frac xy, where yy is coprime with 998244353. Print one integer — the value of xy1xy^{−1}, taken modulo 998244353, where y1y^{−1} is an integer such that yy11(mod998244353)yy^{−1}≡1 (mod 998244353).

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 12\frac12.

思路:比較簡單的思路就是d[i][j]d[i][j]表示前ii個數滿足條件時且第ii個數等於jj的方案數。但是題目給的數範圍太大。

考慮到題目最多給50個區間,那麼我們把題目所給數的區間離散化,那麼最多可以得到100個區間,且每個數的範圍區間是連續的。

因爲題目要求遞減,則可以用d[i][j]d[i][j]表示前ii個數用了第jj個及其後面的區間的方案數,那麼答案就是d[n][0]d[n][0]
現在的問題就是如何處理同一個區間存在多個數的情況以及要保證他們的大小滿足題目要求。
轉移如下:
d[i][j]+=d[k][j+1]CLj+ik1ik(k<iLjj)d[i][j]+=d[k][j+1]*C_{L_j+i-k-1}^{i-k}(k<i,L_j表示第j個區間的長度)
即將區間[k+1,i][k+1,i]裏的數都放在第jj個區間,並用組合數選取iki-k個值(可重複)一一對應即可。

#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;
}

紀念第一次變成master\color{#fbbc05}{master}

發佈了386 篇原創文章 · 獲贊 255 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章