chuansongmen
首先有一个
O(m5)
的DP,其中m为变换后可取到的最大值。
然后猜猜猜
发现每个数,最多加前两个数中的最小值,那么就猜不存在一种变换,使其中一个数大于100,写完DP后assert了一下,发现RE了…
那么就猜不大于150,就过了…
转移的时候去掉无效的转移常数就贼小
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <assert.h>
using namespace std;
const int N=160,P=1e9+7;
int t,n,a[N],f[N][N][N];
inline void add(int &x,int y){
if((x+=y)>=P) x-=P;
}
int main(){
scanf("%d",&t);
while(t--){
memset(f,0,sizeof(f)); memset(a,0,sizeof(a));
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
if(n==1){
printf("%d\n",1);
continue;
}
f[2][a[2]][a[1]]=1;
for(int i=2;i<=150;i++)
for(int j=0;j<=150;j++)
for(int k=0;k<=150;k++)
if(f[i][j][k])
for(int s=0;s<=j && s<=k;s++){
assert(a[i+1]+s<=150);
add(f[i+1][a[i+1]+s][j-s],f[i][j][k]);
}
printf("%d\n",f[100][0][0]);
}
return 0;
}