1 条题解

  • 0
    @ 2025-8-24 22:30:37

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar LZH_LOVE_ZRG
    **

    搬运于2025-08-24 22:30:37,当前版本为作者最后更新于2021-04-13 19:37:37,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    这是一道比较良心的弱省签到题,考察考生的基本代码能力。

    这里介绍几种 22 比较简单的方法:

    Solution 11

    对于每一个数 aia_i,我们可以用 ai\sqrt{a_i} 的时间来枚举出这个数所有的因数。

    具体实现为:用一个循环 jj 枚举,每对数分别为 jjai÷ja_i\div j

    我们用一个桶来存储每个数作为因数出现次数,

    然后最后用一个循环来累加所有答案。

    时间复杂度:O(i=1i<=nai+n)O(\sum\limits_{i=1}^{i<=n} \sqrt{a_i}+n)

    代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define il inline
    using namespace std;
    const int N=5e5+10;
    int read(){//没有多大用的快读
        int f=1,s=0;
        char x=getchar();
        while(x<'0'||x>'9'){
            if(x=='-') f=-1;
            x=getchar();
        }
        while(x>='0'&&x<='9'){
            s=s*10+x-'0';
            x=getchar();
        }
        return f*s;
    }
    int a[N],b[N];//b即为桶
    int main(){
        int n=read();
        for(int i=1;i<=n;i++){
            a[i]=read();
            for(int j=1;j*j<=a[i];j++){
                if(a[i]%j!=0) continue;//关键判断
                int ans1=j,ans2=a[i]/j;
                b[ans1]++;
                if(ans1!=ans2)//特判
                    b[ans2]++;
            }
        }
        ll ans=0;//爆int警告
        for(int i=1;i<=n;i++)
            ans+=(ll)b[a[i]]-1;//累加,减一是减去自己的贡献
        cout<<ans;
        return 0;
    }
    

    Solution 22

    对于每一个 aia_i,改为枚举其倍数并累加其贡献。

    用桶记录每个数出现的次数,再用一个数 jj 枚举 aia_i 乘上的因数。

    贡献的次数就是 bi×bi×j+bi×(bi1)b_i\times b_{i\times j}+b_i\times (b_i-1),后者就是 aia_i 是自己的倍数的情况。

    时间复杂度:调和级数时间复杂度,即为 O(maxai×logmaxai)O(\max{a_i} \times \log{\max{a_i}})

    代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define il inline
    using namespace std;
    const int N=5e5+10;
    int read(){
        int f=1,s=0;
        char x=getchar();
        while(x<'0'||x>'9'){
            if(x=='-') f=-1;
            x=getchar();
        }
        while(x>='0'&&x<='9'){
            s=s*10+x-'0';
            x=getchar();
        }
        return f*s;
    }
    int a[N],b[N];
    int main(){
        int n=read();
        for(int i=1;i<=n;i++)
        	b[read()]++;
        ll ans=0;
        for(int i=1;i<=N;i++){
        	for(int j=2;i*j<=N;j++)
        		ans+=b[i]*b[i*j];
        	ans+=b[i]*(b[i]-1);
    	}
        cout<<ans;
        return 0;
    }
    

    更新日志:

    • 2021/4/13 更正了时间复杂度的计算;
    • 2021/4/14 增加了第 22 种解题方法;
    • 2021/4/17 感谢 houzhiyuan 大佬的批评指正,更改了第 22 种方法的计算。
    • 1

    信息

    ID
    6681
    时间
    1000ms
    内存
    512MiB
    难度
    3
    标签
    递交数
    0
    已通过
    0
    上传者