首页 > 其他 > 详细

小易喜欢的数列, 网易笔试题

时间:2020-06-22 13:11:53      阅读:58      评论:0      收藏:0      [点我收藏+]

动态规划

f[i][j] 表示数列的长度为i, 并且以数j结尾的合法序列的数量。

f[i][j] += f[i-1][l], 其中l,j满足合法序列的要求

//暴力法:时间:O(N*K*K), 空间:O(NK)
//40%通过
import java.util.*;
public class Main {
    static int mod = 1000000007;
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(), k = sc.nextInt();
        int[][] f  = new int[n+1][k+1];
        Arrays.fill(f[1], 1); f[1][0] = 0;
        for(int i=2; i <= n; i++) {
            for(int j=1; j <= k; j++) {
                for(int l=1; l <= k; l++) {
                    if((l <= j) || (l % j != 0)) {
                        f[i][j] = (f[i][j] + f[i-1][l])  % mod;
                    }
                }
            }
        }
        //System.out.println(Arrays.deepToString(f));
        int res = 0;
        for(int i=1; i <= k; i++) res = (res + f[n][i]) % mod;
        System.out.println(res);
    }
}

优化:

条件为:(l <= j) || (l % j != 0),满足条件的数量明显较多,因此,我们用满足和不满足的和减去不满足的数量,就等于满足条件的数量。取反条件变成为:l % j == 0 && l != j

取反集以后求f[i][j]枚举的数量从k下降到了k/j。k + k / 2 + k / 3 +...+k/k = k *(1 + 1/2 + ... + 1 /k) 约等于 k * ln(k+1) + 0.5, 因此,问题复杂度从O(K*K) 下降到了O(K*logK)

// 时间:O(NKlogK)
import java.util.*;
public class Main {
    static int mod = 1000000007;
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(), k = sc.nextInt();
        int[][] f  = new int[n+1][k+1];
        Arrays.fill(f[1], 1); f[1][0] = 0;
        
        for(int i=2; i <= n; i++) {
            int sum = 0;
            for(int j=1; j <= k; j++) sum = (sum + f[i-1][j]) % mod;
            for(int j=1; j <= k; j++) {
                f[i][j] = sum;
                for(int l=j; l <= k; l = l + j) {
                    if(l!= j) {
                        f[i][j] = (f[i][j] + mod - f[i-1][l])  % mod;
                    }
                }
            }
        }
        //System.out.println(Arrays.deepToString(f));
        int res = 0;
        for(int i=1; i <= k; i++) res = (res + f[n][i]) % mod;
        System.out.println(res);
    }
}

小易喜欢的数列, 网易笔试题

原文:https://www.cnblogs.com/lixyuan/p/13176223.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!