0
点赞
收藏
分享

微信扫一扫

牛牛与数组


链接:​​https://ac.nowcoder.com/acm/problem/21738​​​
 

题目描述

牛牛喜欢这样的数组:
1:长度为n
2:每一个数都在1到k之间
3:对于任意连续的两个数A,B,A<=B 与(A % B != 0) 两个条件至少成立一个

请问一共有多少满足条件的数组,对1e9+7取模

输入描述:


输入两个整数n,k 1 ≤ n ≤ 10 1 ≤ k ≤ 100000


输出描述:


输出一个整数


示例1

输入

复制2 2


2 2


输出

复制3


3


示例2

输入

复制9 1


9 1


输出

复制1


1


示例3

输入

复制3 3


3 3


输出

复制15


15


示例4

输入

复制2 1234


2 1234


输出

复制1515011


1515011


思路 :  该题是参考的其他网友的,大致思路知道了。动态规划是真难。

dp[i][j] 表示长度为 i 的 , 以 j 结尾的 符合条件的数组个数 , 把握住 , 长度为 i 的数组 和 长度为 i- 1 的数组的长度 。

dp[i][j] 是 dp[i-1][j] 加上一个元素 x 得到的 , 他应该是 所有以 i-1 长度的数组个数 减轻 不符合 条件的数组 个数.

条件 3 , 任意一个 连续的 A , B , 都有  A<=B  或者 A%B!=0  , 也就是 A 不能是 B的倍数 .看代码能理解。

#include <iostream> 
#include <cstdio>
#include <algorithm>
#include <string>
using namespace std ;
typedef long long LL ;
/*
牛牛与数组

*/
const int MAX = 1050 ;
const int inf = 0x3f3f3f3f ;
const int mod = 1e9+7 ;
int n , k ;
int dp[20][100001] ;
// dp[i][j] 表示长度为 i 且尾数为 j的数组个数

int main(){

cin >> n >> k ;

for(int i = 0 ; i<=k; i++ ) {
dp[1][i] = 1 ;
// 表示长度为 1 的数组 个数是 1
}
int sum = 0 ;
int sum1 = 0 ;
for(int i = 2 ; i<=n; i++ ) {

sum = 0 ;
// 长度为 i-1 的数列数目
for(int j = 1 ; j<=k ; j++ ) {
sum +=dp[i-1][j] ;
sum %=mod ;
}
for(int j = 1 ; j<=k ; j++ ) {
sum1 = 0 ;
// 枚举的是 j 的倍数 ,
// j = 1 , 2 3 4 5 ..k
// j = 2 , 4 ,6 , .. k
for(int x = 2*j ; x <=k ; x+=j) {
sum1 +=dp[i-1][x] ;
sum1 %=mod ;
}
// 长度为 i且以j结尾的 数组个数 = 长度为 i-1 的数组个数 - 长度为 i-1 的且以 是 j 的倍数的数组个数


dp[i][j] = (sum- sum1) %mod ;
}


}
int ans = 0 ;
for(int i = 1 ; i<= k ; i++ ) {
ans +=dp[n][i] ;
ans %=mod ;
}

cout<<ans <<endl ;
return 0 ;
}

 

 

举报

相关推荐

0 条评论