先離散化,設 \(f_i\) 爲考慮前 \(i\) 個元素的方案數,枚舉第 \(i\) 個元素處在第 \(j\) 個區間,同時枚舉一塊兒在第 \(j\) 個區間的元素個數,用組合數計算方案數,\(DP\) 過程當中處理組合數就是 \(O(n^3)\) 了。c++
第一題要算 \(n\) 個元素放到值域爲 \(m\) 的區間中造成不降序列的方案數,第二題要算 \(n\) 個元素放到值域爲 \(m\) 的區間中造成嚴格遞增序列的方案數,且每一個元素能夠不選,但最後一個元素必須選,第一題的不降序列其實就是隨便放,用隔板法便可獲得 \(\binom{n+m-1}{m-1}\),轉化一下第二題的模型就能發現其方案數和第一題同樣,也能夠推導證實:git
第一題:spa
#include<bits/stdc++.h> #define maxn 110 #define p 998244353 using namespace std; typedef long long ll; template<typename T> inline void read(T &x) { x=0;char c=getchar();bool flag=false; while(!isdigit(c)){if(c=='-')flag=true;c=getchar();} while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();} if(flag)x=-x; } int n,tot; ll val=1; int l[maxn],r[maxn],s[maxn]; ll f[maxn],g[maxn]; ll inv(ll x) { ll v=1,y=p-2; while(y) { if(y&1) v=v*x%p; x=x*x%p,y>>=1; } return v; } int main() { read(n); for(int i=1;i<=n;++i) { read(l[i]),read(r[i]),r[i]++,val=val*inv(r[i]-l[i])%p; s[++tot]=l[i],s[++tot]=r[i]; } sort(s+1,s+tot+1),tot=unique(s+1,s+tot+1)-s-1; for(int i=1;i<=n;++i) l[i]=lower_bound(s+1,s+tot+1,l[i])-s,r[i]=lower_bound(s+1,s+tot+1,r[i])-s; f[0]=1; for(int i=tot-1;i;--i) { g[0]=1; for(int j=1;j<=n;++j) g[j]=g[j-1]*(s[i+1]-s[i]+j-1)%p*inv(j)%p; for(int j=n;j;--j) { if(l[j]>i||r[j]<=i) continue; for(int k=j;k;--k) { if(l[k]<=i&&r[k]>i) f[j]=(f[j]+f[k-1]*g[j-k+1]%p)%p; else break; } } } printf("%lld",f[n]*val%p); return 0; }
第二題:code
#include<bits/stdc++.h> #define maxn 1010 #define p 1000000007 using namespace std; typedef long long ll; template<typename T> inline void read(T &x) { x=0;char c=getchar();bool flag=false; while(!isdigit(c)){if(c=='-')flag=true;c=getchar();} while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();} if(flag)x=-x; } int n,tot; ll ans; int l[maxn],r[maxn],s[maxn]; ll f[maxn],g[maxn]; ll inv(ll x) { ll v=1,y=p-2; while(y) { if(y&1) v=v*x%p; x=x*x%p,y>>=1; } return v; } int main() { read(n); for(int i=1;i<=n;++i) read(l[i]),read(r[i]),s[++tot]=l[i],s[++tot]=++r[i]; sort(s+1,s+tot+1),tot=unique(s+1,s+tot+1)-s-1; for(int i=1;i<=n;++i) l[i]=lower_bound(s+1,s+tot+1,l[i])-s,r[i]=lower_bound(s+1,s+tot+1,r[i])-s; f[0]=1; for(int i=1;i<tot;++i) { g[0]=1; for(int j=1;j<=n;++j) g[j]=g[j-1]*(s[i+1]-s[i]+j-1)%p*inv(j)%p; for(int j=n;j;--j) if(l[j]<=i&&r[j]>i) for(int k=j,t=0;k;--k) t+=l[k]<=i&&r[k]>i,f[j]=(f[j]+f[k-1]*g[t]%p)%p; } for(int i=1;i<=n;++i) ans=(ans+f[i])%p; printf("%lld",ans); return 0; }