-
题意:给你一个数\(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; }
相关文章
- 01-27Codeforces Round #740 D2 (Div. 2, based on VK Cup 2021 - Final (Engine))
- 01-27Codeforces Round #740 (Div. 2, based on VK Cup 2021 - Final (Engine)) D1. Up the Strip (simplified v
- 01-27Codeforces Round #740 (Div. 2, based on VK Cup 2021 - Final (Engine)) D2. Up the Strip (数学,DP)
- 01-27Codeforces Round #740 D2 (Div. 2, based on VK Cup 2021 - Final (Engine))
- 01-27Codeforces Round #740 (Div. 2, based on VK Cup 2021 - Final (Engine)) (CF1561D1 & D2 Up the Strip)
- 01-27Codeforces Round #740 (Div. 1, based on VK Cup 2021 - Final (Engine)) 题解