• 计蒜客 30999


    题目链接:https://nanti.jisuanke.com/t/30999

    样例输入
    2
    5
    8


    样例输出
    8
    14

    题意:

    squarefree数是指不含有完全平方数( 1 除外)因子的数,

    现在一个数字 $n$,可以表示成两个squarefree数 $a,b$ 相乘,即 $n = ab$,

    假设 $fleft( n ight)$ 代表了 $n$ 分解成不同的数对 $left( {a,b} ight)$ 的个数,

    现在给你一个 $n$,要求 $fleft( 1 ight) + fleft( 2 ight) + cdots + fleft( n ight)$。

    题解:

    不难发现,若 $n$ 含有一个因子是立方数乃至更高次方数,则此时 $fleft( n ight) = 0$,例如 $fleft( {2^3 imes 3} ight) = 0,fleft( {3^4 } ight) = 0$;

    则剩下来的数,因子最多就是平方数,不妨举些例子来看每个因子能提供多少贡献:

    最开始是 $fleft( 1 ight) = 1$,因为只有 $1 = 1 imes 1$,然后我们给它乘上一些因子……

      1、乘上指数为 $1$ 的因子,例如 $fleft( {1 imes 2} ight)$,加进来的 $2$ ,可以添加在原来$1  imes 1$的乘号左边($2 imes 1$),也可以添加在右边($1 imes 2$),所以贡献了“$ imes 2$”,即 $fleft( {1 imes 2} ight) = fleft( 1 ight) imes 2$;

      2、乘上指数为 $2$ 的因子,例如 $fleft( {1 imes 2^2 } ight)$,加进来的 $2^2$,它不能全部添加在某一边,只能拆开来,一半添加在乘号左边,一半添加在乘号右边,即$2 imes 2$,所以贡献了“$ imes 1$”,即 $fleft( {1 imes 2^2} ight) = fleft( 1 ight) imes 1$。

    那么依次类推,再在后面乘上一些因子,同样的道理,指数为 $1$ 则贡献为“$ imes 2$”,指数为 $2$ 则贡献为“$ imes 1$”。

    很容易的就能得到递推规律:假设 $n$ 的最小素因子是 $p$,则有 $n = m imes p^x$,我们分两种情况讨论:

      1、$x = 1$,$p$ 的贡献为“$ imes 2$”,就有 $fleft( n ight) = fleft( m ight) imes 2$;

      2、$x = 2$,$p$ 的贡献为“$ imes 1$”,就有 $fleft( n ight) = fleft( m ight)$;

    那么,现在的关键就是求得 $1$ 到 $2 imes 10^7$ 的每个数字的最小素因子,线性筛素数的时候可以顺带求出。

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn=2e7+5;
    const int MAX=2e7;
    
    int n;
    int mpf[maxn]; //存储最小素因子
    
    /************************** 线性筛 - st **************************/
    int prime[maxn];
    bool isPrime[maxn];
    void Screen() //欧拉筛法求素数
    {
        register int cnt=0;
        memset(isPrime,1,sizeof(isPrime));
        isPrime[0]=isPrime[1]=0;
        for(int i=2;i<=MAX;i++)
        {
            if(isPrime[i]) prime[cnt++]=i, mpf[i]=i;
            for(int j=0;j<cnt;j++)
            {
                if(i*prime[j]>MAX) break;
                isPrime[i*prime[j]]=0, mpf[i*prime[j]]=prime[j];
                if(i%prime[j]==0) break;
            }
        }
    }
    /************************** 线性筛 - ed **************************/
    
    long long f[maxn];
    
    int main()
    {
        Screen();
    
        f[1]=1;
        for(int i=2;i<=MAX;i++)
        {
            int mm = mpf[i];
            if((long long)mm*mm < MAX && (long long)mm*mm*mm < MAX && i%(mm*mm*mm) == 0) f[i]=0;
            else if((long long)mm*mm < MAX && i%(mm*mm) == 0) f[i]=f[i/mm/mm];
            else f[i]=2*f[i/mm];
        }
        for(int i=2;i<=MAX;i++) f[i]+=f[i-1];
    
        int T;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d",&n);
            printf("%lld
    ",f[n]);
        }
    }
  • 相关阅读:
    聚美优品面试题
    前端开发常用的网站
    JS 正则表达式大全
    软件工程作业二
    大三个人简述
    2019期末总结
    2019春第一次课程设计实验报告
    2019第十二周作业
    2019第十一周作业
    2019第十周作业
  • 原文地址:https://www.cnblogs.com/dilthey/p/9580641.html
Copyright © 2020-2023  润新知