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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章