小易喜欢的数列

https://www.nowcoder.com/practice/49375dd6a42d4230b0dc4ea5a2597a9b?tpId=90&tqId=30787&tPage=1&rp=1&ru=/ta/2018test&qru=/ta/2018test/question-ranking

题目描述

小易非常喜欢拥有以下性质的数列:
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,希望你能帮他求出有多少个是他会喜欢的数列。

 

很基本的动态规划问题:

dp[i][j]保存以j结尾的数列长度为i的符合条件的数列的个数

先求出所有长度为i-1的满足条件的数列的个数和

再去掉不满足条件的那部分

主要排除的是前一位i-1位末尾能够能够整除i位的这种情况

public class Main {
    static final int mod = 1000000007;
    public static void main(String[] args) {
         Scanner scan=new Scanner(System.in);
         int n=scan.nextInt();
         int k=scan.nextInt();
         int[][] dp=new int[n+1][k+1];
         dp[0][1]=1;
         for(int i=1;i<=n;i++) {
             int sum=0;
             for(int j=1;j<=k;j++) {
                 sum=(sum+dp[i-1][j])%mod;
             }
             for(int j=1;j<=k;j++) {
                 int p=2;
                 int invalid=0;
                 while(j*p<=k) {
                     invalid=(invalid+dp[i-1][j*p])%mod;
                     p++;
                 }
                 dp[i][j]=(sum-invalid)%mod;
             }
         }
         int sum=0;
         for(int i=1;i<=k;i++) {
             sum=(sum+dp[n][i])%mod;
         }
         System.out.println(sum);      
    }
}

时间复杂度O(n*k*logk)

posted @ 2019-05-12 12:19  LeeJuly  阅读(309)  评论(0)    收藏  举报