• 约数问题集


    一:求约数个数 

    约数个数定理

    a.分解质因数(一个合数可以分通过质因数分解彻底)

    b.因数和(如何得来:将分解质因数的分开然后相乘共f(n)个)

    int get_num(int n)
    {
        int tot=1;
        for(int i=2;i*i<=n;++i)
        {
            if(n%i==0)
            {
                int x=0;
                while(n%i==0)
                {
                    n/=i;
                    ++x;
                }
                tot*=(x+1)
            }
        }
        if(n>1) tot*=2;//质数
        return tot;
    }
    ll f(ll x)
    {
        ll res=0,i;
        for(i=1;i*i<x;++i)
            if(x%i==0) res+=2;
        if(i*i==x) ++res;
        return res;
    }

    打表大法:

    自身为因子:

    for(int i=1; i<maxn/2; ++i)
    {
        for(int j=1; i*j<maxn; ++j) //板子的本身为j=2,当j=2时因子不算本身
        {
            //这里j=1的用意就是本身也算因子与下面不符
            num[i*j]++;
        }
    }

    自身不为因子:

    for(int i=1; i<maxn/2; ++i)
    {
        for(int j=2; i*j<maxn; ++j) //j=2不算自身为因子
        {
            num[i*j]++;
        }
    }

     二:求约数和:

    约束和定理

    a.求和公式 f(n)=(p1^0+p1^1+p1^2+…p1^a1)(p2^0+p2^1+p2^2+…p2^a2)…(pk^0+pk^1+pk^2+…pk^ak)化简乘积和便可理解为什么这样便是因数和

    b.等比数列化解求和公式

    ll get_sum(ll n)//返回n的约数和
    {
        ll res=1;
        for(ll i=2;i*i<=n;++i)
        {
            if(n%i==0)
            {
                ll x=0;
                while(n%i==0)
                {
                    n/=i;
                    ++x;
                }
                res*=((1-Quick_pow(i,x+1)/(1-i)));//等比数列前n项和
            }
        }
        if(n>1) res*=(1+n);
        return res;
    }

    无自身:

    for(int i=1; i<N/2; i++)
        for(int j=2; j*i<N; j++)
            a[i*j]=a[i*j]+i;

     有自身:

    for(int i=1; i<maxn; ++i)
    {
        for(int j=1; i*j<maxn; ++j) //板子的本身为j=2,当j=2时因子不算本身
        {
            a[i*j]=a[i*j]+i;
        }
    }

    eg:

    HUD1215-求因子和

     1 #include<stdio.h>
     2 #include<string.h>
     3 
     4 const int N=500000+5;
     5 int a[N];
     6 
     7 int main()
     8 {
     9     int t,b;
    10     for(int i=1;i<N/2;i++)
    11         for(int j=2;j*i<N;j++)
    12         a[i*j]=a[i*j]+i;
    13 
    14     scanf("%d",&t);
    15     while(t--)
    16     {
    17         scanf("%d",&b);
    18         printf("%d
    ",a[b]);
    19     }
    20     return 0;
    21 }

     

    HDU-2521求反素数(他本身也算因子)

     1 #include<cstdio>
     2 #include<string.h>
     3 #define LL long long
     4 #define maxn 5100
     5 using namespace std;
     6  
     7 int num[maxn];
     8 int main()
     9 {
    10     memset(num,0,sizeof(num));
    11     for(int i=1;i<maxn;++i)
    12     {
    13         for(int j=1;i*j<maxn;++j)//板子的本身为j=2,当j=2时因子不算本身
    14         {                        //这里j=2的用意就是本身也算因子。
    15             num[i*j]++;
    16         }
    17     }
    18     int n;
    19     scanf("%d",&n);
    20     while(n--)
    21     {
    22         int a,b;
    23         scanf("%d%d",&a,&b);
    24         int ans;
    25         int MAX=0;
    26         for(int i=a;i<=b;++i)
    27         {
    28             if(num[i]>MAX)
    29             {
    30                 MAX=num[i];
    31                 ans=i;
    32             }
    33         }
    34         printf("%d
    ",ans);
    35     }
    36 }
    #include<bits/stdc++.h>
    using namespace std;
    int n,a,b,maxnum,maxindex;
    int get_num(int n){//求n的因子个数
        int tot=1;
        for(int i=2;i*i<=n;++i){
            if(n%i==0){
                int x=0;
                while(n%i==0){
                    n/=i;
                    x++;
                }
                tot*=(x+1);
            }
        }
        if(n>1) tot*=2;
        return tot;
    }
    int main(){
        while(cin>>n){
            while(n--){
                cin>>a>>b;maxnum=0;maxindex=a;
                for(int i=a;i<=b;++i){
                    int tmp=get_num(i);
                    if(tmp>maxnum){maxindex=i;maxnum=tmp;}
                }
                cout<<maxindex<<endl<<maxnum<<endl;
            }
        }
        return 0;
    }

    #1284 : 机会渺茫(共同约数个数-即为最大公约数的因数个数)

    #include<bits/stdc++.h>
    typedef long long ll;
    using namespace std;
    const int mod=1e9+7;
    
    ll f(ll x)
    {
        ll res=0,i;
        for(i=1;i*i<x;++i)
            if(x%i==0) res+=2;
        if(i*i==x) ++res;
        return res;
    }
    
    ll gcd(ll a,ll b)
    {
        ll c;
        while(b){
            c=a%b;
            a=b;
            b=c;
        }
        return a;
    }
    int main()
    {
        ll n,m;cin>>n>>m;
        ll tmp1=f(n),tmp2=f(m);
        ll tmp3=f(gcd(n,m));
        ll cnt=tmp1*tmp2;
        ll x=gcd(cnt,tmp3);
        cout<<cnt/x<<" "<<tmp3/x<<endl;
        return 0;
    }

  • 相关阅读:
    String substring(int start,int end)截取当前字符串中指定范围内的字符串
    String字符串是不变对象,内容一旦创建不可改变,若改变一定会创建新对象
    StringBuilder修改字符串内容,增,删,改,插
    startsWith(),endsWith()判断当前字符串是否是以给定字符串开始或结尾的
    length()返回当前字符串的字符个数
    indexOf()字符位置
    charAt()检测回文
    手把手教你猜字小游戏
    release 和 drain
    c专家编程 ,c语言运行时环境
  • 原文地址:https://www.cnblogs.com/waryan/p/12182271.html
Copyright © 2020-2023  润新知