暑假acwing算法总结18:约数

  • 约数
  • 求一个数的所有约数
  • 可以用vector存储所有约数但要判重和排序,也可以用set直接存储不用判重并且不用排序
//定于vector函数
vector<int> sc(int n)
{
    vector<int>res;
    for(int i=1;i<=n/i;i++)
    {
        if(n%i==0)
        {
            res.push_back(i);
            if(i!=n/i)
            res.push_back(n/i);
        }
    }
    sort(res.begin(),res.end());
    return res;
}
-------------------------------------------------------------
for(int i=1;i<=n/i;i++)
{
    if(n%i==0)
    s.insert(i),s.insert(n/i);
}//set自动排序加去重
  • 求一个数的约数个数
  • 定理一:任何一个数可以表示为
  • x=p1a1* p2a2*……*pnan
  • 则其对应的约数个数是(a1+1) * (a2+1) * …… * (an+1)
  • 因为p是质数,其约数形式也是和x形式相同,所以随着a的变化,其就代表一个约数,a的组合数就是约数个数,也就是乘法原理
  • 比如24=23 * 31所以约数个数就是(指数可以为0)C41 * C21=8
  • 求一个数的约数和
  • 定理二
  • 对应的约数之和为:(p10+p11+……p1a1) * … * (pk0+pk1……+pkak)
  • 例如24=(20+21+22+2^3) * (30+31)
  • 展开式就是代表每一项约数相加也就是约数和
  • 就是1+3+2+6+4+12+8+24=60
  • !对于以上的俩个定理基于分解质因数的计算,都需要用hash表来映射存储底数也就是hash的下标也是最小质因数的值,指数是hash值
  • 上代码
#include<iostream>
#include<unordered_map>

using namespace std;
typedef long long LL;
const int mod=1e9+7;
int main()
{
    int t;cin>>t;
    unordered_map<int,int>hash;
    while(t--)
    {
        int x;cin>>x;
        for(int i=2;i<=x/i;i++)
        {
            while(x%i==0)
            {
                x/=i;
                hash[i]++;
            }
        }
        if(x>1)hash[x]++;
    }
    LL res=1;
    for(auto x:hash)res*=x.second+1,res%=mod;
    cout<<res<<endl;
    return 0;
}
//2021-07-13/20:02
#include<iostream>
#include<unordered_map>

using namespace std;
typedef long long LL;
const int mod=1e9+7;
int main()
{
    int n;cin>>n;
    unordered_map<int,int>hash;
    while(n--)
    {
        int x;cin>>x;
        for(int i=2;i<=x/i;i++)
        {
            while(x%i==0)
            {
                x/=i;
                hash[i]++;
            }
        }
        if(x>1)hash[x]++;
    }
    LL res=1;
    for(auto x:hash)
    {
        int p=x.first,q=x.second;//p是底数q是指数
        LL t=1,ans=0;
        q++;
        while(q--)
        {
            ans=(t+ans)%mod;
            t=t*p%mod;
        }
        res=res*ans%mod;
    }
    cout<<res<<endl;
    return 0;
}
//2021-07-13/21:47
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值