1. 程式人生 > >小易喜歡的數列(網易18校招內推)

小易喜歡的數列(網易18校招內推)

小易非常喜歡擁有以下性質的數列:
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
#include <iostream>
using namespace std;
int main()
{
    int n, k;
    int res = 0;
    int m = 1000000007;
    cin >> n >> k;
    //i表示數列長度、j表示數列以j結尾
    int a[11][100001];
    for(int i = 1; i <= k; i++)
        a[1][i] = 1;
    int sum, sum1;
    for(int i = 2; i <= n; i++)
    {
        sum = 0;
        //長度為i-1的數列數目
        for(int j = 1; j <= k; j++)
        {
            sum += a[i-1][j];
            sum %= m;
        }
        for(int j = 1; j <= k; j++)
        {
            sum1 = 0;
            for(int x = j+j; x <= k; x+=j)
            {
                sum1 += a[i-1][x];
                sum1 %= m;
            }
            //長度為i尾數為j的數列數目 = 長度為i-1的所有 減去 長度為i-1尾數是j的倍數的
            a[i][j] = (sum - sum1) % m;
        }
    }
    //int res;
    for(int j = 1; j <= k; j++)
    {
        res += a[n][j];
        res %= m;
    }

    cout << res;
    return 0;
}
這裡使用動態規劃。a[i][j]表示長度為i以j結尾的數列,滿足dp條件:根據長度為i-1的數列數能得到的長度為i的數列數,長度為i尾數為j的數列數 = 長度為i-1的數列數 - 長度為i-1尾數是j的倍數的。初始置i=1的a[1][j]為1,最後輸出a[n][j]。