约数问题集

一:求约数个数 

约数个数定理

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\n",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\n",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;
}

 

 

 

posted @ 2020-01-12 11:50  waryan  阅读(161)  评论(0编辑  收藏  举报