bzoj 3309: DZY Loves Math 莫比乌斯反演

本文探讨了一种计算特定数论函数的方法,该函数涉及正整数的质因数最大幂指数。通过数学推导,文章提出了一种有效的算法来解决给定范围内两数的特定数论函数之和的问题,利用数论函数的性质和前缀和技巧优化计算过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

对于正整数n,定义 f(n)f(n)f(n)nnn 所含质因子的最大幂指数。例如
f(1960)=f(23∗51∗72)=3,f(10007)=1,f(1)=0f(1960)=f(2^3 * 5^1 * 7^2)=3, f(10007)=1, f(1)=0f(1960)=f(235172)=3,f(10007)=1,f(1)=0
给定正整数a,b,求∑i=1n∑j=1mf(gcd(i,j))\sum_{i=1}^{n}\sum_{j=1}^{m}f(gcd(i,j))i=1nj=1mf(gcd(i,j))

Input

第一行一个数T,表示询问数。
接下来T行,每行两个数a,b,表示一个询问。

Output

对于每一个询问,输出一行一个非负整数作为回答。

Sample Input

4

7558588 9653114

6514903 4451211

7425644 1189442

6335198 4957

Sample Output

35793453939901

14225956593420

4332838845846

15400094813
HINT

【数据规模】

T<=10000

1<=a,b<=10^7

分析:
推一波式子可得,
∑i=1n∑j=1mf(gcd(i,j))\sum_{i=1}^{n}\sum_{j=1}^{m}f(gcd(i,j))i=1nj=1mf(gcd(i,j))
∑D=1nf(D)∑i=1⌊nD⌋μ(d)∗⌊nDd⌋∗⌊mDd⌋\sum_{D=1}^{n}f(D)\sum_{i=1}^{\lfloor\frac{n}{D}\rfloor}\mu(d)*\lfloor\frac{n}{Dd}\rfloor*\lfloor\frac{m}{Dd}\rfloorD=1nf(D)i=1Dnμ(d)DdnDdm
∑T=1n⌊nT⌋⌊mT⌋∑d∣Tμ(d)∗f(Td)\sum_{T=1}^{n}\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor\sum_{d|T}\mu(d)*f(\frac{T}{d})T=1nTnTmdTμ(d)f(dT)
现在就是求后面那个东西的前缀和。
g(T)=∑d∣Tμ(d)∗f(Td)g(T)=\sum_{d|T}\mu(d)*f(\frac{T}{d})g(T)=dTμ(d)f(dT)
因为要想μ(d)\mu(d)μ(d)不为000,满足
d=p1α1∗p2α2∗....∗pkαkd=p_1^{\alpha_1}*p_2^{\alpha_2}*....*p_k^{\alpha_k}d=p1α1p2α2....pkαk
其中αi=[0,1]\alpha_i=[0,1]αi=[0,1]
考虑对于一个TTT,他的幂次只有减111或不变。也就是说,一开始最大的数,改变后还是最大的。
我们把αi\alpha_iαi分成两类,AAA为最大的数(包括和他一样的),BBB为不是最大的数。
组合数知识可以知道,在BBB中选出奇数个和偶数个的方案数是一样的,除非BBB为空集。
假设BBB不为空,此时无论AAA如何选,BBB中奇偶数一样,而贡献正好相反,所以总贡献为000
如果BBB为空,说明AAA全是同一个数,除非全选最大值才会变。如果不变恰好为000,所以减了111贡献为
−(−1)k-(-1)^k(1)kkkk为质数个数。
考虑怎样求这个东西。我们先找到所有无平方因子数,然后枚举他的幂,枚举幂其实复杂度是很小的,可以看做线性。

代码:

/**************************************************************
    Problem: 3309
    User: liangzihao
    Language: C++
    Result: Accepted
    Time:17588 ms
    Memory:313792 kb
****************************************************************/
 
#include <iostream>
#include <cstdio>
#include <cmath>
#define LL long long
 
const int maxn=1e7+7;
 
using namespace std;
 
LL T,a,b,n,m,ans,cnt;
LL prime[maxn],not_prime[maxn],mu[maxn],f[maxn];
 
void get(LL n)
{
    mu[1]=1;
    for (LL i=2;i<=n;i++)
    {
        if (!not_prime[i])
        {
            prime[++cnt]=i;
            mu[i]=-1;
        }
        for (LL j=1;j<=cnt;j++)
        {
            if (prime[j]*i>n) break;
            not_prime[i*prime[j]]=1;
            if (i%prime[j]==0)
            {
                mu[i*prime[j]]=0;
                break;
            }
            mu[i*prime[j]]=-mu[i];
        }
    }    
    f[1]=0;
    for (LL i=2;i<=n;i++)
    {
        if (mu[i])
        {
            for (LL j=i;j<=n;j=j*i)
            {
                f[j]=-mu[i];
            }
        }
    }           
    for (LL i=1;i<=n;i++) f[i]+=f[i-1];
}
 
int main()
{
    scanf("%lld",&T);
    get(1e7);   
    while (T--)
    {
        scanf("%lld%lld",&n,&m);        
        if (n>m) swap(n,m);
        ans=0;
        for (LL i=1,last;i<=n;i=last+1)
        {
            last=min(n/(n/i),m/(m/i));
            ans+=(n/i)*(m/i)*(f[last]-f[i-1]);
        }
        printf("%lld\n",ans);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值