2018 南京网络预赛Sum

题意

链接

定义 $f(x)$ 为满足以下条件的有序二元组 $(a, b)$ 的方案数(即 $(a, b)$ 与 $(b, a)$ 被认为是不同的方案):

  • $x= ab$
  • $a$ 和 $b$ 均无平方因子(即因子中没有除1之外的完全平方数)

求 $displaystyle sum_{i=1}^nf(i), 1 leq nleq 2 imes 10^7$.

分析

显然,$f(n)$ 是积性函数,考虑线性筛。

  1. 当 $x$为素数时, $f(x)=2$,即 $(1,x)$ 和 $(x,1)$;
  2. 当 $x$ 的最小质因子为 $p$,且 $p mid frac{x}{p}$ 时,$f(x) = f(p)f(frac{x}{p}) = 2f(frac{x}{p})$;
  3. 当 $x$ 的最小的质因数为 $p$,且 $p mid frac{x}{p}$
    • 如果 $p mid frac{x}{p^2}$,那么 $x$ 中的 $p$ 的指数至少为3,即不管如何划分 $(a, b)$,两个数中一定有一个数其 $p$ 的指数大于等于2,即不存在合法的方案
    • 否则, $x$中 $p$ 的指数就为2,把这两个 $p$ 分别分给 $a$ 和 $b$,剩余的 $frac{x}{p^2}$就是一个子问题,即 $f(x) = f(frac{x}{p^2}) = f(frac{x}{p})f(frac{1}{p}) = f(frac{x}{p})/2$
#include<bits/stdc++.h>
using namespace std;

const int maxn = 2e7 + 10;
int n;
int vis[maxn], primes[maxn], primeCnt;
int f[maxn], s[maxn];       //f(i)的前缀和

void seive()
{
    f[1] = 1;
    for(int i = 2;i <= maxn;i++)
    {
        if(!vis[i])
        {
            primes[++primeCnt] = i;
            f[i] = 2;
        }
        for(int j=1;j <= primeCnt && (long long)i * primes[j] <= maxn;j++)
        {
            vis[i *primes[j]] = true;
            if(i % primes[j] == 0)
            {
                f[i *primes[j]] = (i / primes[j] % primes[j] == 0)? 0: f[i/primes[j]];
                break;
            }
            else  f[i * primes[j]] = f[i] * 2;
        }
    }
}

int main()
{
   seive();
   for(int i = 1;i <= maxn;i++)  s[i] = s[i-1]+f[i];

   int T;
   scanf("%d", &T);
   while(T--)
   {
       scanf("%d", &n);
       printf("%d
", s[n]);
   }
}

参考链接:https://oi.men.ci/jsk-30999/#%D0%B4%D0%B0%D0%BB%D0%B5%D0%B5

原文地址:https://www.cnblogs.com/lfri/p/11262808.html