好叭,是两个简单的约数的定理,小学奥数水平
一个是约数定理,一个是约数和定理
感觉自己知识还是学得不系统啊……
acm都学到这了基础知识还不全……
思路来源
https://blog.csdn.net/piaocoder/article/details/47954385
概念
由唯一分解定理
n的每个约数q,不妨在 ... 每个素因子前做个抉择,
是有还是没有这个因子,有的话有几个(下限为0个,上限为个)
故每个因子都有(+1)种选择,
共有()*()*...*()种选择,
每种选择对应唯一的一个约数,因为素因子两两互质
而对于式
我们计算某一项的时候,从每一个括号里取一项,最后相乘出来的结果,
一定是某个约数,而且不同取法的约数两两不同,不重不漏得到所有约数的和
其实就是母函数的多项式相乘啦……
约数定理
定义:因子个数函数τ定义为正整数n的所有正因子个数,记为τ(n)
则τ(n)=()*()*...*()
typedef long long ll;
ll prime[maxn],cnt;
//筛素数从略,cnt为素数个数
ll fac_cnt(ll n)//约数个数
{
ll ans=1;
for(int i=0;i<cnt;++i)
{
if(prime[i]*prime[i]>n)break;
if(n%prime[i]==0)
{
int num=0;//prime[i]出现次数
while(n%prime[i]==0)
num++,n/=prime[i];
ans*=(num+1);
}
}
if(n>1)ans*=2;//n为出现一次的素因子
return ans;
}
约数和定理
定义:因子和函数σ定义为整数n的所有正因子之和,记为σ(n)
则σ(n)=
而由等比数列求和,
σ(n)=
考虑到σ(n)比较大应该要取模mod
分子搞一下快速幂,分母搞一下逆元,可求
typedef long long ll;
const int mod=1e9+7;
ll prime[maxn],cnt;
//筛素数从略,cnt为素数个数
//ll快速幂从略
ll fac_sum(ll n)//约数和
{
ll ans=1;
for(int i=0;i<cnt;++i)
{
if(prime[i]*prime[i]>n)break;
if(n%prime[i]==0)
{
int num=0;//prime[i]出现次数
while(n%prime[i]==0)
num++,n/=prime[i];
(ans*=(modpow(prime[i],num+1,mod)-1)*modpow(prime[i]-1,mod-2,mod)%mod)%=mod;//前提mod是质数且与prime[i]-1互质
}
}
if(n>1)(ans*=(1+n)%mod)%=mod;//n为出现一次的素因子
return ans;
}