• 【数论】关于因数个数的题


    (d(x)) 表示 (x) 的约数个数 , (sigma(x)) 表示x的约数和;
    若正整数 (m) 的标准分解式为 (m=p_1^{a_1}p_2^{a_2} ... p_k^{a_k})
    (m) 所含因数的个数 (d(m)=(a_1+1)(a_2+1)...(a_k+1))
    (m) 所有正因数的和 (sigma(m)=frac{p_1^{a_1}-1}{p_1-1}*frac{p_2^{a_2}-1}{p_2-1}*...*frac{p_k^{a_k}-1}{p_k-1})


    poi1,洛谷P1403

    (sum_{i=1}^{n} {d(i)})(nleq 10^9);
    ([1,n]) 里有约数 (i) 的个数是 (lfloor{frac ni} floor) ;
    类似 整除分块的做法,复杂度(O(2sqrt n))

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    int main()
    {
    	int n;
    	ll ans=0;
    	scanf("%d",&n);
    	for(ll l=1,r;l<n;l=r+1)
    	{
    		r=n/(n/l);
    		ans+=(r-l+1)*(n/l);
    	}
    	printf("%lld
    ",ans);
    }
    

    poi2,洛谷P2323

    (sum_{i=l}^{r} {d(i)})(nleq 10^9);
    做法同poi1:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=5e5+50;
    const int inf=0x3f3f3f3f;
    int main()
    {
        ll x,y,num1=0,num2=0;
        scanf("%lld%lld",&x,&y);
        x--;
        for(ll i=1,j;i<=x;i=j+1)
        {
            j=x/(x/i);
            num1+=(x/i)*(i+j)*(j-i+1)/2;
        }
        for(ll i=1,j;i<=y;i=j+1)
        {
            j=y/(y/i);
            num2+=(y/i)*(i+j)*(j-i+1)/2;
        }
        printf("%lld
    ",num2-num1);
    }
    

    poi3,洛谷P6060

    (sum_{i=1}^{n} {d(i^k)})(1leq{n,k}leq{10^7}) ,同时 (T) 个测试样例, (Tleq10^4);
    因为(10^7) 内的数最多有8个不同的因子,所以每个数可以预处理成8项式,再预处理前缀和。

    假如要筛出大量数能分解的因数个数(比如这道题),那么线性筛的预处理(O(n+8))
    不知道该怎么说,下面代码的预处理(参考题解代码来的)很巧妙,(只可意会不可言传

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int inf=0x3f3f3f3f;
    const int mod=998244353;
    const int maxn=1e7+5;
    const int N=1e7;
    
    int pri[maxn],pp[maxn][9],temp[maxn],pre[maxn];
    inline void init()
    {
        pp[1][0]=1;
        for(int i=2;i<=N;i++)
        {
            if(!pri[i])
            {
                pri[++pri[0]]=i;pp[i][0]=pp[i][1]=1;pre[i]=1;temp[i]=1;
            }
            for(int j=1,t;j<=pri[0];j++)
            {
                t=i*pri[j];if(t>N)break;
                pri[t]=1;
                if(i%pri[j])temp[t]=1,pre[t]=i;else temp[t]=temp[i]+1,pre[t]=pre[i];
                for(int k=8;k>=1;k--)pp[t][k]=(pp[pre[t]][k]+pp[pre[t]][k-1]*temp[t])%mod;
                pp[t][0]=pp[pre[t]][0];
                if(i%pri[j]==0)break;
            }
        }
        for(int i=2;i<=N;i++)
            for(int j=0;j<=8;j++)pp[i][j]=(pp[i-1][j]+pp[i][j])%mod;
    }
    int main()
    {
        init();
        int T,n,k;
        scanf("%d",&T);
        while(T--)
        {
            ll ans=0;
            scanf("%d%d",&n,&k);
            for(int i=8;i>=0;i--)
                ans=(ans*k%mod+pp[n][i])%mod;
            printf("%lld
    ",ans);
        }
    }
    
  • 相关阅读:
    sysybench-测试工具
    pip安装到指定目录的方案对比
    更好的创建构造函数的方式
    DeDeCMS-v5.7-漏洞分析
    DVWA靶场
    Fastadmin前台Getshell漏洞分析
    Yii反序列化漏洞分析
    SparkGraphX中的PR算法和pregel迭代算法
    关于linux下,ls vi等命令失效的解决方法(配置下环境变量出现问题)
    埋点的三种方式
  • 原文地址:https://www.cnblogs.com/kkkek/p/12297663.html
Copyright © 2020-2023  润新知