版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/qq_35950004/article/details/85097851
%%%唐老师杜教筛博客课后练习题
不过网上好像没题解啊,好像唐老师也是分段打表的…
但是可以Min_25筛
显然这个
是积性函数,
然后好像就完了,稳稳的Min_25筛套路,不要用什么map记忆化,Min_25筛这个东西由于是二维的状态,分分钟MLE,分段存还要多个log,还不如不存快,目前4400ms稳居倒数第一,希望大家让我这个倒数第一更有含金量一点.
#include<bits/stdc++.h>
#define maxn 100005
#define LL long long
using namespace std;
int n,sn,id;
int h[maxn],a[maxn],pr[maxn],cnt_pr,sh[maxn];
LL g[maxn],sg[maxn];
inline int ID(int a){ return a <= sn ? a : id - n/a + 1; }
void sieve()
{
sn = sqrt(n);
id = cnt_pr = 0;
for(int i=1;i<=n;i++)
a[++id] = i = (n / (n / i)),
g[id] = 1ll * i * (i+1) / 2 - 1,
h[id] = i - 1;
for(int i=1;i<=sn;i++)
if(h[i]!=h[i-1])
{
pr[++cnt_pr] = i , sg[cnt_pr] = sg[cnt_pr-1]+i,sh[cnt_pr] = sh[cnt_pr-1] + 1;
for(int j=id,lim=i*i;a[j]>=lim;j--)
g[j] -= i * (g[ID(a[j]/i)] - sg[cnt_pr-1]),
h[j] -= h[ID(a[j]/i)] - sh[cnt_pr-1];
}
}
map<int,LL>mp[maxn];
LL S(int a,int b)
{
if(a < pr[b])
return 0;
//if(mp[b].count(a)) return mp[b][a];
LL ret = (g[ID(a)] - h[ID(a)]) - (sg[b-1] - sh[b-1]);
for(int i=b;i<=cnt_pr && pr[i]*pr[i]<=a;i++)
for(int x=pr[i];1ll*x*pr[i]<=a;)
ret += S(a/x,i+1)*(x-1),
ret += (x=x*pr[i])-1;
return ret;
}
int main()
{
//freopen("1.in","r",stdin);
for(;~scanf("%d",&n);)
{
sieve();
printf("%lld\n",S(n,1)+1);
}
}