Codeforces Round #740 (Div. 2, based on VK Cup 2021 - Final (Engine)) D1. Up the Strip (simplified v

Codeforces Round #740 (Div. 2, based on VK Cup 2021 - Final (Engine)) D1. Up the Strip (simplified v

  • 题意:给你一个数\(x\),每次有两种操作可以选择,一是从\(x\)跳到\([1,x-1]\)的任意一个数,二是跳到\(\lfloor \frac{x}{z} \rfloor\ \ (z \in[2,x])\).问你从\(x\)到一有多少种方案.

  • 题解:首先很容易写出dp公式,\(dp[t]=\sum_{i=t-1}^{t}dp[i]+\sum_{j=2}^{t}dp[\lfloor \frac{t}{j} \rfloor]\),前一个式子直接前缀和就能求出,后面的式子看到下取整求和,不难想到可以用数论分块\(O(\sqrt n)\)得出,这样就可以\(O(n \sqrt n)\)解决此题。

  • 代码:

    #include <bits/stdc++.h>
    #define ll long long
    #define fi first
    #define se second
    #define pb push_back
    #define me memset
    #define rep(a,b,c) for(int a=b;a<=c;++a)
    #define per(a,b,c) for(int a=b;a>=c;--a)
    const int N = 1e6 + 10;
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    typedef pair<int,int> PII;
    typedef pair<ll,ll> PLL;
    ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
    
    ll n,m;
    ll dp[N];
    
    int main() {
        scanf("%lld %lld",&n,&m);
        dp[n]=1;
        ll sum=0;
        for(int i=n;i>=1;--i){
            dp[i]=(dp[i]+sum)%m;
            for(int l=2,r=0;l<=i;l=r+1){
                r=min(i,i/(i/l));
                dp[i/l]+=dp[i]*(r-l+1);
                dp[i/l]%=m;
            }
            sum=(sum+dp[i])%m;
        }
        printf("%lld\n",dp[1]);
        return 0;
    }
    
    
上一篇:Xilinx ACAP介绍


下一篇:pandas