1. 程式人生 > >網易2017內推 [程式設計題]小易喜歡的數列

網易2017內推 [程式設計題]小易喜歡的數列

[程式設計題]小易喜歡的數列
  • 熱度指數:1954時間限制:1秒空間限制:32768K
小易非常喜歡擁有以下性質的數列:
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)


輸出描述:
輸出一個整數,即滿足要求的數列個數,因為答案可能很大,輸出對1,000,000,007取模的結果。
示例1

輸入

2 2

輸出

3

思路:對普通動態規劃進行優化

因為簡單的用動態規劃會超時,所以在計算res[i][j]的時候,先將res中i-1行的元素求和,然後減去其中不符合要求的數字。

package go.jacob.day814;

import java.util.Scanner;

public class Demo2 {
	static final int MOD = 1000000007;

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int k = sc.nextInt();
		//res[i][]j表示第i個數字為j的次數
		int[][] res = new int[n + 1][k + 1];
		res[0][1] = 1;

		for (int i = 1; i <= n; i++) {
			int sum = 0;
			for (int j = 1; j <= k; j++)
				sum = (sum + res[i - 1][j]) % MOD;
			for (int j = 1; j <= k; j++) {
				int p = 2;
				int invalid = 0;
				while (p * j <= k) {
					//計算不符合要求的數字和
					invalid = (invalid + res[i - 1][p * j]) % MOD;
					p++;
				}
				res[i][j] = (sum - invalid + MOD) % MOD;
			}
		}
		int sum = 0;
		for (int i = 1; i <= k; i++)
			sum = (sum + res[n][i]) % MOD;

		System.out.println(sum);
		sc.close();
	}

}