一个数的约数个数的求法:
对于一个数
x
x
x,由算术基本定理 (任何一个大于
1
1
1的自然数,都可以唯一的分解成有限个质数的乘积)
即
x
=
p
1
a
1
p
2
a
2
…
…
p
k
a
k
x = p_1^{a_1}p_2^{a_2}……p_k^{a_k}
x=p1a1p2a2……pkak
另
t
=
p
1
b
1
p
2
b
2
…
…
p
k
b
k
(
0
<
=
b
i
<
=
a
i
)
t = p_1^{b_1}p_2^{b_2}……p_k^{b_k} (0<=b_i<=a_i)
t=p1b1p2b2……pkbk(0<=bi<=ai)
那么
t
t
t一定是
x
x
x的一个约数
所以根据指数的不同,
x
x
x的约数也不同,指数的所有不同取法囊括了
x
x
x的所以约数
所以:
x
x
x的约数个数为
(
a
1
+
1
)
(
a
2
+
1
)
(
a
3
+
1
)
…
…
(
a
k
+
1
)
(a_1+1)(a_2+1)(a_3+1)……(a_k+1)
(a1+1)(a2+1)(a3+1)……(ak+1)
一个数的约数之和的求法:
由上面可以知道:
x
=
p
1
a
1
p
2
a
2
…
…
p
k
a
k
x = p_1^{a_1}p_2^{a_2}……p_k^{a_k}
x=p1a1p2a2……pkak
对于其中一个质数
p
i
p_i
pi,它的所有可能个数在
0
a
i
0~a_i
0 ai之间
根据母函数的有关知识:
x
x
x的约数之和为:
(
p
1
0
+
p
1
1
+
…
…
+
p
1
a
1
)
(
p
2
0
+
p
2
1
+
…
…
+
p
2
a
2
)
…
…
(
p
k
0
+
p
k
1
+
…
…
+
p
k
a
k
)
(p_1^0+p_1^1+……+p_1^{a_1})(p_2^0+p_2^1+……+p_2^{a_2})……(p_k^0+p_k^1+……+p_k^{a_k})
(p10+p11+……+p1a1)(p20+p21+……+p2a2)……(pk0+pk1+……+pkak)
题目
简单版:
给定n个正整数ai,请你输出这些数的乘积的约数之和,答案对1e9+7取模。
输入格式
第一行包含整数n。
接下来n行,每行包含一个整数ai。
输出格式
输出一个整数,表示所给正整数的乘积的约数之和,答案需对1e9+7取模。
数据范围
1≤n≤100, 1≤ai≤2∗1e9
const int mod = 1e9+7;
int main()
{
int n; cin>>n;
map<int,int> prime; //得到所有的因子和其次数
while(n--)
{
int x; cin>>x;
for(int i=2;i<=x/i;i++)
while(x%i==0)
{
prime[i]++;
x/=i;
}
if(x>1) prime[x]++;
}
ll res=1;
map<int,int>::iterator it;
for(it=prime.begin();it!=prime.end();it++) //遍历每一个因子
{
int p=it->first,a=it->second;
ll sum=1;
while(a--) sum=(sum*p+1)%mod;
res=res*sum%mod;
}
cout<<res<<endl;
return 0;
}
困难版:
假设现在有两个自然数A和B,S是AB的所有约数之和。
请你求出S mod 9901的值是多少。
输入格式
在一行中输入用空格隔开的两个整数A和B。
输出格式
输出一个整数,代表S mod 9901的值。
数据范围
0≤A,B≤5×1e7
首先介绍一个求p0+p1+p2+……+pk的快速求法(log级):
设函数sum(p,k) =p0+ p1+p2+……+pk
= (p0+ p1+p2+……+pk/2)+(pk/2+1+……+pk)
当k为奇数时,两边的个数是相等的
= (p0+ p1+p2+……+pk/2)(1+pk/2+1)
= sum(p,k/2)(1+pk/2+1)
如果k是偶数,先算求出来k-1时的结果,然后每一个都乘上p,最后+1
= p*sum(p,k-1)+1;
#include<cstdio>
#include<cmath>
#include<ctime>
#include<cstring>
#include<iostream>
#include<map>
#include<set>
#include<stack>
#include<queue>
#include<string>
#include<vector>
#define ll long long
#define ull unsigned long long
#define up_b upper_bound
#define low_b lower_bound
#define m_p make_pair
#define mem(a) memset(a,0,sizeof(a))
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define inf 0x3f3f3f3f
#define endl '\n'
#include<algorithm>
using namespace std;
inline ll read()
{
ll x=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
while('0'<=ch&&ch<='9') x=x*10+ch-'0', ch=getchar();
return f*x;
}
const int mod = 9901;
int power(int a,int b)
{
a %= mod;
int res=1;
while(b) { if(b&1) res=res*a%mod; a=a*a%mod; b>>=1; }
return res;
}
int sum(int p,int k)
{
if(k == 0) return 1;
if(k & 1) return sum(p, k / 2) % mod * (1 + power(p, k / 2 + 1)) % mod;
return (p % mod * sum(p, k - 1) + 1) % mod;
}
int main()
{
int a,b;
cin>>a>>b;
if(a==0) { cout<<0<<endl; return 0; } //特判
int res=1;
for(int i=2;i<=a;i++)
{
int s=0;
while(a%i==0)
{
s++;
a/=i;
}
if(s) res=res*sum(i,s*b) % mod;
}
cout<<res<<endl;
return 0;
}