知识总结:
虽然第i个数要不大于前i-1个数的均值,但不能只存前i-1个数的均值。
因为在进行多次整除的过程中会有数漏掉
#include<stdio.h>
#include<string.h>
int main(){
//获取输入内容
int n;
int ini[41];
int mod=1e9+7;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&ini[i]);
//test:for(int i=1;i<=n;i++) printf("%d",ini[i]);
//创建动态规划所用的2个3维数组,简化使用设为一个4维数组
int dp[2][41][1601][2];
memset(dp,0,sizeof(dp));
int lastflag;
//根据第一个数进行初始化
if(ini[1]==-1){
for(int j=0;j<41;j++){
dp[0][j][j][1]=1;
}
}
else{
int d=ini[1];
dp[0][d][d][1]=1;
}
//test:
/*
for(int i=0;i<41;i++){
for(int j=0;j<41;j++){
printf("%d ",dp[0][i][j][0]);
}
printf("\n");
}
*/
//从输入数组的第二个开始遍历
for(int i=2;i<=n;i++){
//第一次dp【0】-》dp【1】,之后dp【1】-》dp[0]
int flag1=i%2;
int flag2=(i+1)%2;
lastflag=flag2;
memset(dp[flag2],0,sizeof(dp[flag2]));
//-1
if(ini[i]==-1){
for(int j=0;j<41;j++){
for(int k=0;k<1601;k++){
int ad = k/(i-1);
for(int torf=0;torf<2;torf++){
if(dp[flag1][j][k][torf]==0) continue;
for(int nownum=j;nownum<=ad;nownum++){
dp[flag2][nownum][k+nownum][1]=(dp[flag2][nownum][k+nownum][1]+dp[flag1][j][k][torf])%mod;
}
if(torf==1){
for(int nownum=0;nownum<j;nownum++){
dp[flag2][nownum][k+nownum][0]=(dp[flag2][nownum][k+nownum][0]+dp[flag1][j][k][torf])%mod;
}
}
}
}
}
}//-1test
/*
for(int i=0;i<41;i++){
for(int j=0;j<41;j++){
printf("%d ",dp[flag2][i][j][1]);
}
printf("\n");
}
*/
//不是-1
else{
int d=ini[i];
for(int j=0;j<41;j++){
for(int k=0;k<1601;k++){
int ad = k/(i-1);
for(int torf=0;torf<2;torf++){
if(dp[flag1][j][k][torf]==0) continue;
for(int nownum=j;nownum<=ad;nownum++){
if(nownum!=d) continue;
dp[flag2][nownum][k+nownum][1]=(dp[flag2][nownum][k+nownum][1]+dp[flag1][j][k][torf])%mod;
}
if(torf==1){
for(int nownum=0;nownum<j;nownum++){
if(nownum!=d) continue;
dp[flag2][nownum][k+nownum][0]=(dp[flag2][nownum][k+nownum][0]+dp[flag1][j][k][torf])%mod;
}
}
}
}
}
}
//-1test
}
int num=0;
for(int j=0;j<41;j++){
for(int k=0;k<1601;k++){
for(int l=0;l<2;l++){
num=(num+dp[lastflag][j][k][l])%mod;
}
}
}
printf("%d",num);
}
个人总结:写的过程中效率太低,解决办法就是模块化的去写,写完一部分测试一部分,闷头写到末尾再从头找错是最打击人的积极性的。