小a的子序列(2019牛客寒假算法基础集训营 Day1-F)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011815404/article/details/88380539

【题目描述】

小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;
}

猜你喜欢

转载自blog.csdn.net/u011815404/article/details/88380539