• [编程题] 小易喜欢的数列 dp


    https://www.nowcoder.com/question/next?pid=6291726&qid=112729&tid=12736753

    [编程题] 小易喜欢的数列

    时间限制: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

    输出例子1:
    3




      dp[i][j]表示第i个位置放的数是j的时候的合法方案是多少。
      转移:dp[i - 1][j] = sigma(dp[i][1...j]) - (sigma(dp[i][j的因子]);

    #include <bits/stdc++.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    const int maxn = 1e5 + 20;
    const int MOD = 1e9 + 7;
    LL dp[2][maxn];
    void add(LL &x, LL y) {
        x = (x + y + MOD) % MOD;
    }
    int prime[maxn][12];
    void init_prime() {
        for (int i = 2; i <= maxn - 20; ++i) {
            if (prime[i][0]) continue; // 这个数i不是质数
            for (int j = i; j <= maxn - 20; j += i) {
                prime[j][++prime[j][0]] = i;
            } //prime[12] = {2, 3}
        }
    }
    vector<int> vc[maxn];
    
    void ca(int num, int to, int now) {
        if (now > num / 2) return;
        if (num % now == 0) vc[num].push_back(now);
        else return;
        if (to == 0) to = 1;
        for (int i = to; i <= prime[num][0]; ++i) {
            ca(num, i, now * prime[num][i]);
        }
    }
    
    void show() {
        int f = 18;
        for (int i = 0; i < vc[f].size(); ++i) {
            cout << vc[f][i] << " ";
        }
        cout << endl;
    }
    
    void work() {
        int n, k;
        cin >> n >> k;
        int now = 0;
        LL sum = k;
        for (int i = 1; i <= k; ++i) {
            dp[0][i] = 1;
        }
        init_prime();
        for (int i = 1; i <= k; ++i) {
            ca(i, 0, 1);
        }
    //    show();
        for (int i = n - 1; i >= 1; --i) {
            now = !now;
            dp[now][1] = sum;
            for (int j = 2; j <= k; ++j) {
                dp[now][j] = sum;
    //            for (int f = 2 * j; f <= k; f += j) {
    //                add(dp[now][j], -dp[!now][f]);
    //            }
                for (int f = 0; f < vc[j].size(); ++f) {
                    add(dp[now][j], -dp[!now][vc[j][f]]);
                }
            }
            sum = 0;
            for (int j = 1; j <= k; ++j) {
    //            sum[j] = dp[now][j];
    //            add(sum[j], sum[j - 1]);
                add(sum, dp[now][j]);
            }
        }
        LL ans = 0;
        for (int i = 1; i <= k; ++i) {
            add(ans, dp[now][i]);
        }
        cout << ans << endl;
    }
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        work();
        return 0;
    }
    View Code


  • 相关阅读:
    INewPolygonFeedback接口(实时显示所画多边形的面积)
    RichTextBox追加文本信息,并根据信息的多少自动下移
    Google tile和TMS的索引算法
    出差咸阳
    失败的 炸羊排
    年中总结
    Oracle 两个表之间的数据更新
    ArcEngine下,实现图形的擦除操作(Erase操作)
    C#中使用ListView动态添加数据不闪烁(转)
    出差略阳
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/8005549.html
Copyright © 2020-2023  润新知