【题目描述】
小a有一个长度为n的序列,但是他忘了这个序列的样子,他只记得序列中的数大小在[1,V]内
你可以任意选择一些位置,并给它们赋值来组成一段子序列,需要满足序列中的数严格递增
一段子序列的“萌值”定义为序列中除最大数外所有数的乘积,若只有1个数则为1
他想请你求出所有合法子序列的“萌值”的和
不同子序列的定义为:存在某个值不同 或 在原序列中的位置不同
输出答案对10^9+7取模
【输入描述】
两个数n,V
【输出描述】
一个整数表示答案
【样例】
示例1
输入
2 2
输出
5
说明
若X表示不选该位置,那么合法的方案有
1 X = 1
X 1 = 1
1 2 = 1
X 2 = 1
2 X = 1示例2
输入
3 4
输出
55
思路:线性 dp
设 f[i][j] 为截止到第 i 个位置,最大值为 j 的答案的值,同时设 sum 用于统计前 i-1 个位置的和,考虑状态转移:
- 若第 i 个位置放数字,则:f[i][j]=f[i-1][j]+sum,同时考虑下一轮的 j,其中最大的数为当前的 j,因此统计和时 f[i-1][j] 要乘以 j
- 若第 i 个位置不放数字,则:f[i][j]=f[i-1][j]
【源代码】
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#define PI acos(-1.0)
#define E 1e-9
#define INF 0x3f3f3f3f
#define LL long long
const int MOD=1E9+7;
const int N=10000+5;
const int dx[]= {-1,1,0,0};
const int dy[]= {0,0,-1,1};
using namespace std;
int f[N][N];
int main(){
int n,v;
scanf("%d%d",&n,&v);
//截止到第1个位置最大值为i的值均为1
for(int i=1;i<=v;i++)
f[1][i]=1;
for(int i=2;i<=n;i++){
LL sum=1;
for(int j=1;j<=v;j++){
f[i][j]=(f[i-1][j]+sum)%MOD;//放数字
sum=(sum+f[i-1][j]*j)%MOD;//统计和
}
}
LL res=0;
for(int i=1;i<=v;i++)
res=(res+f[n][i])%MOD;
printf("%lld\n",res);
return 0;
}