loj2567APIO2016划艇
Posted paul-guderian
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了loj2567APIO2016划艇相关的知识,希望对你有一定的参考价值。
题目
\\(N\\)个位置,每个位置要么不选,要么选\\([ a_i, b_i ]\\)中的一个数;
问最后的单调上升序列(mod 1e9+7)有多少种;
\\(1 \\le N \\le 500\\)
题解
orz abclzr
直接\\(dp\\)最后一位是什么数字的话只能得到31分
将数字离散化分段,第\\(i\\)段为\\([l_i,r_i)\\),设\\(f_{i,j}\\)表示第i个位置选的数字在第j段的方案数(第0段表示没有)
\\[ f_{i,j} \\ = \\sum_{k=0}^{i-1} \\sum_{l=0}^{j-1} f_{k,l} \\times cal(k+1,i,j) \\ans = \\sum_{i=1}^n \\sum_{j=1}^m f_{i,j} \\\\]其中$cal(l,r,x) \\(表示\\)[l,r)$都不选或者选在第j段并且单调上升的方案数
设 $ [ l,r) $ 这里面有 $ S $ 个包含x区间,x区间的长度为 $ L $
\\[ cal(l,r,x) = \\sum_{i=0}^{S}(^S_i)(^L_{i+1}) = \\sum_{i=0}^{S}(^S_{S-i})(^L_{i+1}) \\思考组合意义:左边选S-i个再在右边选i+1个相当与一起选S+1个\\cal(l,r,x) = (^{S+L}_{S+1}) \\\\]前缀和优化dp即可:\\(O(n^3)\\)
#include<bits/stdc++.h> #define ll long long using namespace std; const int N=1010,mod=1e9+7; int n,tot,sub[N],L[N],R[N],ny[N],l[N],f[N][N]; void inc(int&x,int y){x+=y;if(x>=mod)x-=mod;} int main(){ // freopen("boat.in","r",stdin); // freopen("boat.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;++i){ scanf("%d%d",&L[i],&R[i]); sub[++tot]=L[i]; sub[++tot]=++R[i]; } sort(sub+1,sub+tot+1); tot=unique(sub+1,sub+tot+1)-sub-1; for(int i=1;i<=n;++i){ L[i]=lower_bound(sub+1,sub+tot+1,L[i])-sub; R[i]=lower_bound(sub+1,sub+tot+1,R[i])-sub; } ny[1]=1;for(int i=2;i<=n;++i)ny[i]=(ll)(mod-mod/i)*ny[mod%i]%mod; for(int i=0;i<tot;++i)f[0][i]=1; for(int i=1;i<tot;++i)l[i]=sub[i+1]-sub[i]; for(int i=1;i<=n;++i){ for(int j=L[i];j<R[i];++j){ int C=l[j],a=l[j],b=1; for(int k=i-1;~k;--k){ inc(f[i][j],(ll)f[k][j-1]*C%mod); if(L[k]<=j&&j<R[k])C=(ll)C*(++a)%mod*ny[++b]%mod; } } for(int j=1;j<tot;++j)inc(f[i][j],f[i][j-1]); } int ans=0;for(int i=1;i<=n;++i)inc(ans,f[i][tot-1]); cout<<ans<<endl; return 0; }
//菜兔兔写的部分分 #include<bits/stdc++.h> #define pb push_back using namespace std; const int N=510,M=2000010,mod=1e9+7; int n,a[N],b[N],len[N],sub[M],tot; int f[M],g[M]; void inc(int&x,int y){x+=y;if(x>=mod)x-=mod;} int main(){ // freopen("boat.in","r",stdin); // freopen("boat.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;++i){ scanf("%d%d",&a[i],&b[i]); for(int j=a[i];j<=b[i];++j)sub[++tot]=j; } sort(sub+1,sub+tot+1); tot=unique(sub+1,sub+tot+1)-sub-1; f[0]=1;for(int i=0;i<=tot;++i)g[i]=1; for(int i=1;i<=n;++i){ a[i]=lower_bound(sub+1,sub+tot+1,a[i])-sub; b[i]=lower_bound(sub+1,sub+tot+1,b[i])-sub; for(int j=a[i];j<=b[i];++j)f[j]=g[j]; for(int j=a[i];j<=tot;++j)inc(g[j]=f[j],g[j-1]); } cout<<g[tot]-1<<endl; return 0; }
以上是关于loj2567APIO2016划艇的主要内容,如果未能解决你的问题,请参考以下文章