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

Description

对于正整数n,定义 f ( n ) f(n) f(n) n n n 所含质因子的最大幂指数。例如
f ( 1960 ) = f ( 2 3 ∗ 5 1 ∗ 7 2 ) = 3 , f ( 10007 ) = 1 , f ( 1 ) = 0 f(1960)=f(2^3 * 5^1 * 7^2)=3, f(10007)=1, f(1)=0 f(1960)=f(235172)=3,f(10007)=1,f(1)=0
给定正整数a,b,求 ∑ i = 1 n ∑ j = 1 m f ( g c d ( 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 = 1 n ∑ j = 1 m f ( g c d ( i , j ) ) \sum_{i=1}^{n}\sum_{j=1}^{m}f(gcd(i,j)) i=1nj=1mf(gcd(i,j))
∑ D = 1 n f ( D ) ∑ i = 1 ⌊ n D ⌋ μ ( d ) ∗ ⌊ n D d ⌋ ∗ ⌊ m D d ⌋ \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}\rfloor D=1nf(D)i=1Dnμ(d)DdnDdm
∑ T = 1 n ⌊ n T ⌋ ⌊ m T ⌋ ∑ d ∣ T μ ( d ) ∗ f ( T d ) \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 ( T d ) g(T)=\sum_{d|T}\mu(d)*f(\frac{T}{d}) g(T)=dTμ(d)f(dT)
因为要想 μ ( d ) \mu(d) μ(d)不为 0 0 0,满足
d = p 1 α 1 ∗ p 2 α 2 ∗ . . . . ∗ p k α k d=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]
考虑对于一个 T T T,他的幂次只有减 1 1 1或不变。也就是说,一开始最大的数,改变后还是最大的。
我们把 α i \alpha_i αi分成两类, A A A为最大的数(包括和他一样的), B B B为不是最大的数。
组合数知识可以知道,在 B B B中选出奇数个和偶数个的方案数是一样的,除非 B B B为空集。
假设 B B B不为空,此时无论 A A A如何选, B B B中奇偶数一样,而贡献正好相反,所以总贡献为 0 0 0
如果 B B B为空,说明 A A A全是同一个数,除非全选最大值才会变。如果不变恰好为 0 0 0,所以减了 1 1 1贡献为
− ( − 1 ) k -(-1)^k (1)k k k k为质数个数。
考虑怎样求这个东西。我们先找到所有无平方因子数,然后枚举他的幂,枚举幂其实复杂度是很小的,可以看做线性。

代码:

/**************************************************************
    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);
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值