HYSBZ 3944 Sum

HYSBZ 3944 Sum

题目描述:

输入正整数 N (N2311) ,求 Ni=1ψ(i) Ni=1μ(i)

题解:

杜教筛模板题。

以欧拉函数为例:

i=1Ndiψ(d)=i=1N(ψ×1)(i)=N(N+1)2

F(x) 表示 xi=1ψ(i) ,那么又有
i=1Ndiψ(d)=id=1Nd=1Nidψ(d)=k=1Nd=1Nkψ(d)=k=1NF(Nk)

所以
F(N)=N(N+1)2i=2NF(Nk)

预处理出前 MAXN23 的答案,然后记忆化搜索即可。对于莫比乌斯函数的推到同理。

题目链接: vjudge 原网站

代码:


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;

#define MAXN 5000007
#define MAXP MAXN / 10
#define MAXM 200007

static int T, pr_tot, prime[MAXP];
static bool npr[MAXN], vis_phi[MAXM], vis_mu[MAXM];
static long long N;
static long long phi[MAXN], mu[MAXN], mem_phi[MAXM], mem_mu[MAXM];

long long solve_phi(long long x)
{
    if (x < MAXN) return phi[x];
    if (vis_phi[N / x]) return mem_phi[N / x];
    long long ans = (x + 1) * x / 2;
    for (long long i = 2, last; i <= x; i = last + 1)
    {
        last = x / (x / i);
        ans -= (last - i + 1) * solve_phi(x / i);
    }
    return vis_phi[N / x] = 1, mem_phi[N / x] = ans;
}

long long solve_mu(long long x)
{
    if (x < MAXN) return mu[x];
    if (vis_mu[N / x]) return mem_mu[N / x];
    long long ans = 1;
    for (long long i = 2, last; i <= x; i = last + 1)
    {
        last = x / (x / i);
        ans -= (last - i + 1) * solve_mu(x / i);
    }
    return vis_mu[N / x] = 1, mem_mu[N / x] = ans;
}


int main()
{
    phi[1] = mu[1] = 1;
    for (int i = 2; i < MAXN; i++)
    {
        if (!npr[i])
            prime[pr_tot++] = i, phi[i] = i - 1, mu[i] = -1;
        for (int j = 0; j < pr_tot && (long long)i * prime[j] < MAXN; j++)
        {
            npr[i * prime[j]] = 1;
            if (i % prime[j])
            {
                phi[i * prime[j]] = phi[i] * (prime[j] - 1);
                mu[i * prime[j]] = -mu[i];
            }
            else
            {
                phi[i * prime[j]] = phi[i] * prime[j];
                mu[i * prime[j]] = 0;
                break;
            }
        }
    }
    for (int i = 1; i < MAXN; i++)
        phi[i] += phi[i-1], mu[i] += mu[i-1];
    for (scanf("%d", &T); T; T--)
    {
        scanf("%lld", &N);
        memset(vis_phi, 0, sizeof(vis_phi));
        memset(vis_mu, 0, sizeof(vis_mu));
        printf("%lld %lld\n", solve_phi(N), solve_mu(N));
    }
    return 0;
}

提交记录(AC / Total = 1 / 6):

Run IDRemote Run IDTime(ms)Memory(kb)ResultSubmit Time
87291121988730460880512RE2017-04-10 10:44:56
872933419888594972102388RE2017-04-10 11:41:49
872934919888831110480644TLE2017-04-10 11:47:29
872938619889180174116MLE2017-04-10 12:01:50
8729427198892854889300WA2017-04-10 12:10:43
872943519889301096489300AC2017-04-10 12:13:44
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值