小易喜欢的序列
题目:小易非常喜欢拥有以下性质的数列:
1、数列的长度为n
2、数列中的每个数都在1到k之间(包括1和k)
3、对于位置相邻的两个数A和B(A在B前),都满足(A <= B)或(A mod B != 0)(满足其一即可)
例如,当n = 4, k = 7
那么{1,7,7,2},它的长度是4,所有数字也在1到7范围内,并且满足第三条性质,所以小易是喜欢这个数列的
但是小易不喜欢{4,4,4,2}这个数列。小易给出n和k,希望你能帮他求出有多少个是他会喜欢的数列。
输入包括两个整数n和k(1 ≤ n ≤ 10, 1 ≤ k ≤ 10^5)
输入:2 2
输出:3
前言
真的搞了好久才搞懂。
思路
举例:输入长度n=3,k=3.
首先创建一个二维数组
int [][] state =new int [n+1][k+1];这里就是动态规划的备忘录法。
state[i][j]表示长度为i,且数列的最后一个数是j的满足条件的数列的个数。
state[i][j]=state[i-1][m](1<=m<=j)
我们可以这样来理解这句代码:
长度为i,结尾为j的数列可以有长度为i-1,结尾为任意1至j的数列后面加上数字j所构成
当然,这里面也包含了非法的数列,这是我们需要判断数列state[i-1][m]中的m是不是j的整数倍,也就是旧数列的结尾的数是不是刚加进来的j的整数倍。
比如 i=2, j=2
state[2][2]=state[1][1]+state[1][2];
state[1][1]其实表示为"1"这样一个数列, state [1][2]表示的是"2"这样一个序列
那么,state[2][2]表示的数列是长度为2并且以2为结尾的数列,他可以是1后面加上2,也可以是2后面加上2所构成。
代码
童山公爵的
package mianshiti;
import java.util.Scanner;
public class Demo4 {
static final int mod = 1000000007;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int k = scanner.nextInt();
int [][] state = new int[n+1][k+1];
state[0][1] = 1;
for(int i=1; i<=n; i++) {
int sum = 0;
for(int j=1; j<=k; j++) {
sum = (sum + state[i-1][j]) % mod;
}
for(int j=1; j<=k; j++) {
int invalid = 0;
int p = 2;
while(p*j <= k) {
invalid = (invalid + state[i-1][p*j]) % mod;
p++;
}
state[i][j] = (sum - invalid + mod) % mod;
}
}
int sum = 0;
for(int i=1; i<=k; i++) {
sum = (sum + state[n][i]) % mod;
}
System.out.println(sum);
scanner.close();
}
}
举n=3,k=3的例子演示下流程
首先创建一个二维数组:
k\n 0 1 2 3
0 0 0 0 0
1 0 0 0 0
2 0 0 0 0
3 0 0 0 0
执行代码
state[0][1] = 1;
表格变为:
k\n 0 1 2 3
0 0 0 0 0
1 1 0 0 0
2 0 0 0 0
3 0 0 0 0
i=1时,
执行完第一个for循环后sum=1
执行完第二个for循环之后表格变为
k\n 0 1 2 3
0 0 0 0 0
1 1 1 0 0
2 0 1 0 0
3 0 1 0 0
i=2时,sum=state[1][1]+state[1][2]+state[1][3]=3;
也就是在1,2,3后面加数字1,2,3
1
2 1 对于j=1时即后面加1时判断有几个非法的数列,我们可以发现state[1][2]和state[1][3]为非法的,所以invalid=2,sum=3-2=1
3 此时state [2][1]=1
1
2 2 同理state [2][2]=3
3
1
2 3 state [2][3]=3
3
表格变为:
k\n 0 1 2 3
0 0 0 0 0
1 1 1 1 0
2 0 1 3 0
3 0 1 3 0
i=3时
sum=1+3+3=7
1 1
1 2
2 2
2 3 1 同理判断第倒数第二个数是不是整数倍是不是1的整数倍
1 3 state [3][1]=1
2 3
3 3
1 1
1 2
2 2
2 3 2 state[3][2]=7
1 3
2 3
3 3
1 1
1 2
2 2
2 3 1 state[3][3]=7
1 3
2 3
33
最后通过for循环计算数列长度为n的符合条件的数列的个数:1+7+7=15