数学知识:约数

 试除法求约数:

#include 
#include 
#include 

using namespace std;

int n;

void get_divisors(int n)
{
    vector res;

    for (int i = 1; i <= n / i; i++)//如果i是n的约数,则n/i==x(x肯定是整数),那么n/x==i(i是整数(因为i是约数))。
    {                               //说明i若是n的约数,则n/i也是n的约数,因此只要判断

约数个数:

#include
#include
using namespace std;

typedef long long LL; 
const int mod = 1e9 + 7;

int main()
{
    int n,x;
    LL ans = 1;//答案先为1,因为后面是用乘法算的,所以不能为0
    unordered_map hash;//纪录某个数的指数,first存数字,second存指数
    scanf("%d",&n);
    while(n--)
    {
        scanf("%d",&x);
        //如果i是x的约数,那么x/i也是x的约数,那么x就可以化成更小的了。如8的约数是2,4,8,那么当i=2时,就可以把8化成4了,在化×成2,这样就是2*2*2,。这样就不会算成2*4而是2*2*2
        //是因为做法要求的是尽量约数要小,指数要大,所以x的约数一定比x/i小,一旦比x/i大了,那说明该数没有约数了,就进行下面的if(x>1)语句
        //质因数从2开始
        for(int i = 2;i <= x/i; ++i)
        {
            while(x % i == 0)
            {
                x /= i;
                hash[i] ++;
            }
        }
        if(x > 1) hash[x] ++;//x的最大公约数可能大于sqrt(x),要特别考虑
    }
    //将统计出来的数按照由图中公式所得出来的结论得出答案
    for(auto i : hash) ans = ans*(i.second + 1) % mod;//%mod是防止整型溢出
    //如案例:2*6*8的约数个数,2的约数为2;6的约数为2、3;8的约数为2、2、2,所以2的指数为5,3的指数为1,由公式得:(5+1)*(1+1)=12
    printf("%d\n",ans);
    return 0;
}

约数之和:

注意:a不仅是质数,而且必须是质因数

#include 
#include 

using namespace std;

typedef long long LL;

const int N = 110, mod = 1e9 + 7;

int main()
{
    int n;
    scanf("%d",&n);

    unordered_map primes;//纪录某个数的指数,first存数字,second存指数

    while (n -- )
    {
        int x;
        scanf("%d",&x);
        //如果i是x的约数,那么x/i也是x的约数,那么x就可以化成更小的了。如8的约数是2,4,8,那么当i=2时,就可以把8化成4了,在化×成2,这样就是2*2*2,。这样就不会算成2*4而是2*2*2
        //是因为做法要求的是尽量约数要小,指数要大,所以x的约数一定比x/i小,一旦比x/i大了,那说明该数没有约数了,就进行下面的if(x>1)语句
        //质因数从2开始
        for (int i = 2; i <= x / i; i ++ )
            while (x % i == 0)
            {
                x /= i;
                primes[i] ++ ;
            }
        if (x > 1) primes[x] ++ ;//x的最大公约数可能大于sqrt(x),要特别考虑
    }

    LL res = 1;
    for (auto p : primes)
    {
        LL a = p.first, b = p.second;
        LL t = 1;
        //将统计出来的数按照由图中公式所得出来的结论得出答案
        while (b -- ) t = (t * a + 1) % mod;//%mod是防止整型溢出,该处用的公式在下面注释写了过程
        res = res * t % mod;
//如案例:2*6*8的约数之和,2的约数为2;6的约数为2、3;8的约数为2、2、2,所以2的指数为5,3的指数为1
//由公式得:t=1*2+1=3,t=3*2+1=7,t=7*2+1=15,t=15*2+1=31,t=31*2+1=63,res=1*63=63。2的5次方就是63
//          t=1*3+1=4,res=63*4=252
    }
    printf("%d\n",res);
    return 0;
}

最大公约数:

#include
using namespace std;

int gcd(int a, int b)
{
    if(a % b == 0)return b;
    return gcd(b,a % b);//这里不用看a和b谁大,因为递归还是会反过来比较,如a比b小,则递归后a%b==a,又是b在前面a在后面
    //例二:4和6的最大公约数
    //a=6 4
    //b=4 2,此时余数为0返回b
}
 
int main()
{
    int n,a,b;
    scanf("%d",&n);
    while(n--) 
    {
        scanf("%d%d",&a,&b);
        printf("%d\n",gcd(a,b));
    }
    return 0;
}

你可能感兴趣的:(哈希算法,算法)