链接: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 ;
}