zoukankan      html  css  js  c++  java
  • CF1558 B. Up the Strip

    https://codeforces.com/problemset/problem/1558/B

    题意:

    n级台阶,求从第n级走到第1级的方案数

    有2种走法

    1、从n走到n-y  y∈[1,n-1]

    2、从n走到n/z  z∈[2,n]

    令f[i]表示从第i级走到第1级的方案数

    f[i]= ∑ f[i-j] + ∑ f[i/k]   j∈[1,i-1],k∈[2,i]

    这是n^2的做法

    前半部分就是一个前缀和,可以O(1)解决

    后半部分可以用除法分块优化到O(n*sqrt(n))

    思考后半部分能否利用类似于前缀或者后缀和优化的方式

    设dp[i]表示从第n级走到第i级的方案数

    枚举j,求哪些数除以j等于i, 发现是i*j到(i+1)*j-1的数除以j等于i,这就可以用后缀和优化一次求出这些数的贡献

    i*j是i的倍数,相当于一共枚举了n以内所有数的倍数次,是nlogn的复杂度

    #include<bits/stdc++.h>
     
    using namespace std;
     
    #define N 4000003
     
    int f[N],dp[N];
     
    int main()
    {
        int n,m,l,r;
        scanf("%d%d",&n,&m);
        dp[n]=f[n]=1;
        for(int i=n-1;i;--i)
        {
            dp[i]=f[i+1];
            for(int j=2;j*i<=n;++j)
            {
                l=j*i;
                r=j*(i+1)-1;
                if(r>n) r=n;
                dp[i]=((dp[i]+f[l])%m-f[r+1]+m)%m; 
            }
            f[i]=(f[i+1]+dp[i])%m;
        }
        printf("%d",dp[1]); 
    }
    作者:xxy
    本文版权归作者和博客园共有,转载请用链接,请勿原文转载,Thanks♪(・ω・)ノ。
  • 相关阅读:
    flex-direction
    flex-grow
    Push API
    ServiceWorker.state
    Using Service Workers
    Promise.then
    Promise()
    Using promises
    node-rsa
    async.waterfall
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/15240366.html
Copyright © 2011-2022 走看看