USACO 2019 JAN Platinum 3 -- Train Tracking 2 发表于 2019-04-25 | 更新于 2019-06-17 | 分类于 动态规划 | 评论数: 摘要给你滑动窗口各位置的区间min,求原序列方案数 Pickupwin: 无从下手啊 Sol: 考虑下为什么区间min会变化 题面解官方题解 首先考虑所有值都相等,可以DP 一个变化代表确定某个位置的值,最终未确定的段就是上面的DP Code1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889#include <cstdio>const int MOD=1000000007;const int MAX=1000000000;const int MAXN=5000011;inline int mul(const int &a, const int &b){ return (int)((1LL*a*b)%(long long)(MOD));}int pow(int t, int k){ int r=1; while(k){ if(k&1) r=mul(r, t); t=mul(t, t); k>>=1; } return r;}inline void add(int &f, const int &v){ f+=v;if(f>=MOD) f-=MOD;}int N, K;int Ans[MAXN];int V[MAXN];int F_[MAXN], *F=&F_[1];int Deal(int l, int v){ //printf("%d %d\n", l, v); if(l<=0) return 1; int x=MAX-v; if(l<K) return pow(x+1, l); F[-1]=1;F[0]=1; for(int i=1;i<K;++i) F[i]=mul(F[i-1], x+1); int tmp=pow(x, K-1); for(int i=K;i<=l;++i){ F[i]=F[i-1]; add(F[i], MOD-mul(F[i-K-1], tmp)); F[i]=mul(F[i], x); add(F[i], F[i-1]); } return F[l];}int main(){ freopen("tracking2.in", "r", stdin); freopen("tracking2.out", "w", stdout); scanf("%d%d", &N, &K); for(int i=1;i<=N-K+1;++i) scanf("%d", &V[i]); for(int i=1;i<N-K+1;++i){ if(V[i]<V[i+1]) Ans[i]=V[i]; if(V[i]>V[i+1]) Ans[i+K]=V[i+1]; } int ANS=1; int p=0; for(int i=1;i<=N;++i){ if(Ans[i]){ ANS=mul(ANS, Deal((i-1)-(p+1)+1, (Ans[i]<Ans[p])?(V[i-K]):((p+1)>(N-K+1)?V[N-K+1]:V[p+1]))); p=i; } } ANS=mul(ANS, Deal(N-(p+1)+1, V[N-K+1])); printf("%d\n", ANS); return 0;}/*6 3999999998999999999999999998999999998*/