BZOJ 4584 [Apio2016]赛艇
題目鏈接
https://www.lydsy.com/JudgeOnline/problem.php?id=4584
題解
首先將BiB_iBi?加111,把派出的數量變成左閉右開的區間,將AiA_iAi?和BiB_iBi?離散化,把題目涉及的區間變成一段段左閉右開的區間。例如,假設給出了[1,4],[2,5],[3,6][1,4],[2,5],[3,6][1,4],[2,5],[3,6]這三個數量的區間,那么離散化之后就變成了
[1,4]→[1,2),[2,3),[3,5)[2,5]→[2,3),[3,5),[5,6)[3,6]→[3,5),[5,6),[6,7) [1,4] \rightarrow [1,2),[2,3),[3,5)\\ [2,5] \rightarrow [2,3),[3,5),[5,6)\\ [3,6] \rightarrow [3,5),[5,6),[6,7) [1,4]→[1,2),[2,3),[3,5)[2,5]→[2,3),[3,5),[5,6)[3,6]→[3,5),[5,6),[6,7)
可以證明,離散化之后的區間個數不超過2n?12n-12n?1。
設f[i][j][k]f[i][j][k]f[i][j][k]表示前iii個位置,第iii個位置必須派出,派出的數量在離散化后的第jjj個區間內,派出數量在這個區間內的一共有kkk個位置的方案數。
f[i][j][1]=∑i′=0i?1∑j′=0j?1∑k=1nf[i′][j′][k]f[i][j][k]=∑i′=0i?1f[i′][j][k?1](k>1) f[i][j][1]=\sum_{i'=0}^{i-1} \sum_{j'=0}^{j-1} \sum_{k=1}^n f[i'][j'][k]\\ f[i][j][k]=\sum_{i'=0}^{i-1} f[i'][j][k-1](k>1) f[i][j][1]=i′=0∑i?1?j′=0∑j?1?k=1∑n?f[i′][j′][k]f[i][j][k]=i′=0∑i?1?f[i′][j][k?1](k>1)
這個還算比較好理解的,后面兩個東西用前綴和轉移即可,然后你就會發現fff數組沒有存在的必要了,可以去掉(卡常,不加這個過不了),最后fff數組的前綴和-1就是答案。
代碼
#include <cstdio> #include <algorithm>int read() {int x=0,f=1;char ch=getchar();while((ch<'0')||(ch>'9')){if(ch=='-'){f=-f;}ch=getchar();}while((ch>='0')&&(ch<='9')){x=x*10+ch-'0';ch=getchar();}return x*f; }const int maxn=500; const int mod=1000000007;int n,l[maxn+10],r[maxn+10],d[maxn*2+10],tot,len[maxn*2+10],sum[maxn+10][maxn*2+10],inv[maxn+10],sf[maxn*2+10][maxn+10];int main() {n=read();for(int i=1; i<=n; ++i){l[i]=read();r[i]=read();d[++tot]=l[i];d[++tot]=r[i]+1;}std::sort(d+1,d+tot+1);tot=std::unique(d+1,d+tot+1)-d-1;for(int i=1; i<=n; ++i){l[i]=std::lower_bound(d+1,d+tot+1,l[i])-d;r[i]=std::lower_bound(d+1,d+tot+1,r[i]+1)-d;}for(int i=1; i<tot; ++i){len[i]=d[i+1]-d[i];}inv[1]=1;for(int i=2; i<=n; ++i){inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;}for(int i=0; i<=tot; ++i){sum[0][i]=1;}for(int i=1; i<=n; ++i){for(int j=0; j<l[i]; ++j){sum[i][j]=sum[i-1][j];}for(int j=l[i]; j<r[i]; ++j){int fuck=1ll*len[j]*sum[i-1][j-1]%mod,pps=fuck;for(int k=i; k>1; --k){int h=1ll*sf[j][k-1]*(len[j]-k+1)%mod*inv[k]%mod;pps+=h;if(pps>=mod){pps-=mod;}sf[j][k]+=h;if(sf[j][k]>=mod){sf[j][k]-=mod;}}sf[j][1]+=fuck;if(sf[j][1]>=mod){sf[j][1]-=mod;}sum[i][j]=(1ll*sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+pps)%mod;if(sum[i][j]<0){sum[i][j]+=mod;}}for(int j=r[i]; j<=tot; ++j){sum[i][j]=(1ll*sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1])%mod;if(sum[i][j]<0){sum[i][j]+=mod;}}}printf("%d\n",(sum[n][tot]+mod-1)%mod);return 0; }轉載于:https://www.cnblogs.com/Canopus-wym/p/10376106.html
總結
以上是生活随笔為你收集整理的BZOJ 4584 [Apio2016]赛艇的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 提升方法---提升树
- 下一篇: HTTPS协议入门