CF479E Riding in a Lift (dp)
比较简单的dp,第一眼的想法肯定直接转移,这样是n^3的复杂度,因此我们需要一些小技巧
仔细观察发现,可以用前缀和来维护答案,这样转移就很快了,只需要找到两个边界点就行
我分了a<b和a>b两种方式讨论,这样比较直观一些。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> using namespace std; typedef long long ll; const int N=1e6+10; const int mod=1e9+7; ll f[5010][5010]; ll sum[5050]; int main(){ int n,a,b,k; cin>>n>>a>>b>>k; int i,j; memset(f,0,sizeof f); f[0][a]=1; for(i=a;i<=n;i++) sum[i]=1; int sign; if(a<b){ for(i=1;i<=k;i++){ for(j=1;j<b;j++){ int sign1=j+b>>1; while(b-sign1<=sign1-j) sign1--; f[i][j]=(sum[sign1]-f[i-1][j])%mod; } sum[0]=0; for(int x=1;x<b;x++) sum[x]=sum[x-1]+f[i][x]; } int ans=0; for(i=1;i<b;i++){ ans=(ans+f[k][i])%mod; } cout<<ans<<endl; } else{ for(i=1;i<=k;i++){ for(j=b+1;j<=n;j++){ int sign1=b+j>>1; while(sign1-b<=j-sign1) sign1++; f[i][j]=(sum[n]-sum[sign1-1]-f[i-1][j])%mod; } sum[0]=0; for(int x=b+1;x<=n;x++) sum[x]=sum[x-1]+f[i][x]; } int ans=0; for(i=b+1;i<=n;i++) ans=(ans+f[k][i])%mod; cout<<ans<<endl; } }
没有人不辛苦,只有人不喊疼