• [dp优化]Chip Move Codeforces1716D


    There is a chip on the coordinate line. Initially, the chip is located at the point 00. You can perform any number of moves; each move increases the coordinate of the chip by some positive integer (which is called the length of the move). The length of the first move you make should be divisible by kk, the length of the second move — by k+1k+1, the third — by k+2k+2, and so on.

    For example, if k=2k=2, then the sequence of moves may look like this: 0→4→7→19→440→4→7→19→44, because 4−0=44−0=4 is divisible by 2=k2=k, 7−4=37−4=3 is divisible by 3=k+13=k+1, 19−7=1219−7=12 is divisible by 4=k+24=k+2, 44−19=2544−19=25 is divisible by 5=k+35=k+3.

    You are given two positive integers nn and kk. Your task is to count the number of ways to reach the point xx, starting from 00, for every x∈[1,n]x∈[1,n]. The number of ways can be very large, so print it modulo 998244353998244353. Two ways are considered different if they differ as sets of visited positions.

    Input

    The first (and only) line of the input contains two integers nn and kk (1≤k≤n≤2⋅1051≤k≤n≤2⋅105).

    Output

    Print nn integers — the number of ways to reach the point xx, starting from 00, for every x∈[1,n]x∈[1,n], taken modulo 998244353998244353.

    Examples

    input

    8 1
    

    output

    1 1 2 2 3 4 5 6 

    input

    10 2
    

    output

    0 1 0 1 1 1 1 2 2 2 

    题意: 有n个点顺序排列在1~n,起点在0,第i次跳跃的距离需要是m+i-1的倍数,且跳跃距离不能为0,问跳到每个点的方案数。

    分析: 设状态为dp[i][j],表示用i次跳跃到达j点的方案数,对于最后一次跳跃可以枚举跳跃长度是m+i-1的多少倍,不过这样显然会超时且超内存,由于跳跃倍数可以是1~∞,这样就有点像完全背包了,所以类比完全背包的递推优化也可以对这道题的递推进行优化:

    这样就把三重循环优化到了两重循环,不过空间上也需要优化,因为650*200000是开不下的,空间优化可以用滚动数组,不过要注意对用完的值进行清空,这点有点类似之前的多校题:[dp]Two Permutations 2022杭电多校第3场

    具体代码如下:

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #define int long long
    8. using namespace std;
    9. const int mod = 998244353;
    10. int dp[2][200005];//用i步走到j的方案数
    11. int ans[200005];
    12. signed main()
    13. {
    14. int n, m;
    15. cin >> n >> m;
    16. for(int i = 1; i*m <= n; i++){
    17. dp[1][i*m] = 1;
    18. ans[i*m]++;
    19. }
    20. for(int i = 2; (2*m+i-1)*i/2 <= n; i++){//这层循环最多700次
    21. for(int j = m; j <= n; j++){
    22. //枚举最后一步是m+i-1的几倍,剩下的距离要用i-1步到达
    23. if(j-(m+i-1) >= 0)//类似完全背包的优化
    24. dp[i&1][j] = (dp[(i-1)&1][j-(m+i-1)]+dp[i&1][j-(m+i-1)])%mod;
    25. ans[j] = (ans[j]+dp[i&1][j])%mod;
    26. }
    27. for(int j = 1; j <= n; j++)
    28. dp[(i-1)&1][j] = 0;
    29. }
    30. for(int i = 1; i <= n; i++)
    31. printf("%lld ", ans[i]);
    32. return 0;
    33. }
    34. //dp[i][j] = dp[i-1][j]+dp[i][j-v[i]]+w[i]

  • 相关阅读:
    色彩空间介绍
    苹果“FindMy”APP
    机器学习/算法工程师面试题目与答案-数学基础部分
    在 Lua 中如何实现高效的内存管理?
    2022最新SLAM面试题汇总(持续更新中)
    使用Docker创建并运行一个create-react-app应用(超简单)
    8Manage:电子寻源采购管理指南
    计算机网络-网络互连和互联网(四)
    2022最新软件测试面试八股文,全网最全最新,堪称地表最强
    uniapp 组件 和 API
  • 原文地址:https://blog.csdn.net/m0_55982600/article/details/126859054