Divisors of the Divisors of An Integer(唯一分解定理+欧拉筛)

Divisors of the Divisors of An Integer


题意:

给定两个函数 d ( n ) 和 s n d d ( n ) d(n)和sndd(n) d(n)sndd(n) d ( n ) d(n) d(n)为n的因子个数, s n d d ( n ) sndd(n) sndd(n)为n的因子的 d ( x ) d(x) d(x)和。例如: s n d d ( 24 ) = d ( 1 ) + d ( 2 ) + d ( 3 ) + d ( 4 ) + d ( 6 ) + d ( 8 ) + d ( 12 ) + d ( 24 ) = 30 sndd(24)=d(1)+d(2)+d(3)+d(4)+d(6)+d(8)+d(12)+d(24)=30 sndd(24)=d(1)+d(2)+d(3)+d(4)+d(6)+d(8)+d(12)+d(24)=30

s n d d ( n ! ) sndd(n!) sndd(n!) n ! = 1 × 2 × 3 × . . . × n n!=1\times2\times3\times...\times n n!=1×2×3×...×n


思路:

根据唯一分解定理:
n ! = p 1 a 1 × p 2 a 2 × p 3 a 3 × . . . × p x a x n!=p_1^{a_1}\times p_2^{a_2} \times p_3^{a_3}\times ...\times p_x^{a_x} n!=p1a1×p2a2×p3a3×...×pxax
所以n的所有因子可以表示为:
n ′ = p 1 b 1 × p 2 b 2 × p 3 b 3 × . . . × p x b x , 其 中 0 ≤ b i ≤ a i n'=p_1^{b_1}\times p_2^{b_2} \times p_3^{b_3}\times ...\times p_x^{b_x},其中0\le b_i \le a_i n=p1b1×p2b2×p3b3×...×pxbx,0biai
所以对于每一个 b i b_i bi都有 a i + 1 a_i+1 ai+1种取值。由于 p i p_i pi为素数,所以 d ( p i x ) = x + 1 d(p_i^{x})=x+1 d(pix)=x+1

在计算答案的时候我们可以计算每一个质因子对答案的贡献。那对于 p 1 p_1 p1这个质因子,它的贡献不就是 d ( p 1 0 ) + d ( p 1 1 ) + . . . + d ( p 1 a 1 ) = ( a 1 + 1 ) + a 1 × ( a 1 + 1 ) 2 d(p_1^0)+d(p_1^1)+...+d(p_1^{a_1})=(a_1+1)+ \cfrac{a_1\times(a_1+1)}{2} d(p10)+d(p11)+...+d(p1a1)=(a1+1)+2a1×(a1+1)

所以最后的答案不就是 ∏ ( a i + 1 ) + a i × ( a i + 1 ) 2 \prod (a_i+1)+ \cfrac{a_i\times(a_i+1)}{2} (ai+1)+2ai×(ai+1)

那n!的所有质因子个数如何求呢?

如果要你算n!中有多少个因子x,那么结果就是n/x的累加。------这是个结论


参考代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll M=10000007;
const int maxn=1e6+10;
ll prime[maxn];
bool vis[maxn];
ll cnt;
void Prime()
{
	for (int i = 2; i < maxn; i++)
	{
		if (vis[i] == false) prime[cnt++] = i;
		for (int j = 0; i * prime[j] < maxn; j++)
		{
			vis[i * prime[j]] = true;
			if (i % prime[j] == 0) break;
		}
	}
}
int main()
{
    Prime();
    ll n;
    while(~scanf("%lld",&n))
    {
        if(n==0)break;
        ll ans=1;
        for(int i=0;i<cnt;i++)
        {
            if(prime[i]>n)break;
            ll sum=0,x=n;
            while(x)
            {
                sum+=x/prime[i];
                x/=prime[i];
            }
            //cout<<sum<<endl;
            ll xx=((sum+1)+(sum*(sum+1)/2))%M;
            ans=ans*xx%M;
        }
        printf("%lld\n",ans);
    }
    system("pause");
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值