Codeforces 1295F. Good Contest dp+組合數學+概率

題意

給你n個區間,[li,ri][l_i,r_i],在每個區間裏面選整數然後要求選出的整數遞減的概率

分析

很老的套路了,考慮分母就是Πi=1n(rili+1)\Pi_{i=1}^{n}{(r_i - l_i + 1)}
分子的話就是單調遞減的dp,右端點+1變成左閉右開離散化之後考慮兩個相鄰的區間我們怎麼選數
下一個區間選的數要在上一個的右邊
然後如果在同一個區間裏面選數:
如果是整數範圍的話就可重複組合,實數範圍內的話就是1/n!1/n!
枚舉有多少個數在同一個區間內就好了

代碼

#include <set> 
#include <map>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <cstdio>
#include <vector> 
#include <cstdlib>
#include <cstring>
#include <climits>
#include <complex>
#include <iostream>
#include <algorithm>

#define fi first
#define se second
#define MP make_pair
#define PB push_back
#define dmp(x) cout << (x) << endl;

using namespace std;

typedef unsigned long long ull;
typedef long long ll;
typedef pair<ll,ll> pii;

const ll N = 110;
const ll mod = 998244353;
const ll inf = 1e15;

inline ll read()
{
  ll p=0; ll f=1; char ch=getchar();
  while(ch<'0' || ch>'9'){if(ch=='-') f*=-1; ch=getchar();}
  while(ch>='0' && ch<='9'){p=p*10+ch-'0'; ch=getchar();}
  return p*f;
}

ll l[N],r[N],n; ll b[N],blen;

ll f[N][N][N]; ll p[N];

ll qpow(ll x,ll k,ll mo)
{
  ll s = 1;
  while(k)
  {
    if(k&1) s = s*x%mo;
    x=x*x%mo; k>>=1;
  }return s;
}

ll inv(ll x){return qpow(x,mod-2,mod);}

ll C(ll x,ll k)
{
  ll s = 1;
  if(k==0) return 1;
  for(ll i=1;i<=k;i++) s = s * (x-i+1) % mod * inv(i) % mod;
  return s;
}

int main()
{
	
  n = read(); blen = 0;
  for(ll i=1;i<=n;i++) l[i] = read(),r[i] = read() , b[++blen] = l[i],b[++blen] = ++r[i];
  ll fm = 1;
  for(ll i=1;i<=n;i++) fm = fm * (r[i] - l[i]) % mod;
  sort(b+1,b+blen+1); blen = unique(b+1,b+blen+1) - (b+1);
  for(ll i=1;i<=n;i++) l[i] = lower_bound(b+1,b+blen+1,l[i]) - b, r[i] = lower_bound(b+1,b+blen+1,r[i]) - b - 1;
  for(ll i=1;i<blen;i++) p[i] = b[i+1] - b[i];
  for(ll i=l[1];i<=r[1];i++) f[1][i][1] = p[i];
  for(ll i=2;i<=n;i++)
    for(ll j=l[i];j<=r[i];j++)
      for(ll t=1;t<i;t++)
        for(ll k=r[i-1];k>=l[i-1];k--)
        {
          if(k<j) break;
          if(j==k)
          {
            f[i][j][t+1] = (f[i][j][t+1] + f[i-1][k][t] * inv(C(p[j]+t-1,t)) % mod * C(p[j]+t,t+1) % mod) % mod;
            break;
          }
          else
          {
            f[i][j][1] = (f[i][j][1] + f[i-1][k][t] * p[j] % mod) % mod;
          }
        }
  
  ll fz = 0;
  for(ll i=1;i<blen;i++)
  {
    for(ll t=1;t<=n;t++) fz = (fz + f[n][i][t]) % mod;
  }

  return printf("%lld\n",fz * inv(fm) % mod),0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章