ZOJ The Sum of Unitary Totient

ZOJ 3808

%%%唐老师杜教筛博客课后练习题
不过网上好像没题解啊,好像唐老师也是分段打表的…
但是可以Min_25筛

显然这个 ϕ ∗ \phi^* ϕ是积性函数,
ϕ ∗ ( p ) = p − 1 \phi^*(p) = p-1 ϕ(p)=p1
ϕ ∗ ( p k ) = p k − 1 \phi^*(p^k) = p^k-1 ϕ(pk)=pk1
然后好像就完了,稳稳的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);
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值