# [LuoguP4808][CCC 2018]平衡树(数论分块+记忆化搜索)(有复杂度证明)

## 分析

$T(n)=\sum_{i=2}^n T(\lfloor \frac{n}{i}\rfloor)+\sqrt{n}$

$T(n)=\sum_{i=2}^{\sqrt{n}} (T(i)+T(\lfloor \frac{n}{i}\rfloor))+\sqrt{n}$

\begin{aligned}T(n)&=\sum_{i=2}^{\sqrt{n}}(\sqrt{i}+\sqrt{\lfloor\frac{n}{i}\rfloor})+\sqrt{n} \\ &\geq \sum_{i=2}^{\sqrt{n}}(2\sqrt{\sqrt{i}\cdot \sqrt{\frac{n}{i}})}+\sqrt{n} \\ &=2\sqrt{\sqrt{n}}+\sqrt{n} \\ &=O(n^{\frac{3}{4}})\end{aligned}

## 代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
#define maxn 10000000
using namespace std;
typedef long long ll;
//小的n用数组,大的n用map记录状态,卡常
ll f[maxn+5];
map<ll,ll>mf;
ll dfs(int n){
if(n==1) return 1;
if(n<=maxn&&f[n]) return f[n];
if(mf.count(n)) return mf[n];
ll ans=0;
for(int l=2,r;l<=n;l=r+1){
r=n/(n/l);
ans+=dfs(n/l)*(r-l+1);
}
if(n<=maxn) f[n]=ans;
else mf[n]=ans;
return ans;
}
int main(){
#ifndef LOCAL
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
#endif
int n;
scanf("%d",&n);

printf("%lld\n",dfs(n));
}

posted @ 2020-12-03 16:41  birchtree  阅读(90)  评论(0编辑  收藏  举报