bzoj 3309: DZY Loves Math(莫比乌斯反演+线性筛)

题面

https://www.lydsy.com/JudgeOnline/problem.php?id=3309

i=1aj=1bf((i,j))

T<=10000,1<=a,b<=107

其中 f(n) n 所含质因子的最大幂指数。


思路

这个反演很简单,假设a<b

ans=T=1anTmTd|Tf(d)μ(Td)

设后面的那堆为 F(T) ,求 F(T) 的前缀和,这是个含 μ 狄利克雷卷积,根据 μ 的特性,我们也能筛出每个 F

明显不是积性,将T d 表示一下

T=pk11pk22...pknn,d=pq11pq22...pqnn

如果存在 qi<ki1 d 没有贡献。考虑有贡献的,若存在两个不同的ki,将 T 的质因子指数分成最大和非最大两类。由于f只取决于最大集合,剩下的集合取奇数偶数方案相同 μ 值抵消,故若存在两个不同 ki F(T)=0

假如全部一样呢? μ 那边取的不在 f 里的集合元素奇偶个数也是一样啊!但有一种情况就是f(d)=ki1,这时多算了 (1)n ,加回一个 (1)n+1

这样就可以愉快地线筛了,记录最小质因子的个数 e[i] ,最小质因子组成的约数 g[i] ,算 F 就是判断一下,然后转移,跟求μ差不多。


代码

#include <bits/stdc++.h>
#define maxn 10000100

using namespace std;

typedef long long LL;

int T, n, m, cnt;
int prime[maxn], g[maxn], e[maxn], F[maxn];
bool Vis[maxn];
LL ans;

void Pre(){
    for(int i = 2; i < maxn; i++){
        if(!Vis[i]){
            prime[++cnt] = i;
            e[i] = F[i] = 1;
            g[i] = i;
        }
        for(int j = 1; j <= cnt; j++){
            if(i * prime[j] >= maxn)  break;
            Vis[i * prime[j]] = true;
            if(i % prime[j] == 0){
                e[i * prime[j]] = e[i] + 1;
                g[i * prime[j]] = g[i] * prime[j];
                int tmp = i / g[i];
                if(tmp == 1)  F[i * prime[j]] = 1;
                else  F[i * prime[j]] = (e[tmp] == e[i * prime[j]]) ? -F[tmp] : 0;
                break;
            }
            else{
                e[i * prime[j]] = 1;
                g[i * prime[j]] = prime[j];
                F[i * prime[j]] = (e[i] == 1) ? -F[i] : 0;
            }
        }
    }
    for(int i = 2; i < maxn; i++)  F[i] += F[i-1];
}

int main(){

    freopen("4-9.in", "r", stdin);
    freopen("4-9.out", "w", stdout);

    Pre();

    scanf("%d", &T);

    while(T --){
        scanf("%d%d", &n, &m);
        if(n > m)  swap(n, m);
        int last;
        ans = 0;
        for(int i = 1; i <= n; i = last+1){
            last = min(n/(n/i), m/(m/i));
            ans += 1LL * (n / i) * (m / i) * (F[last] - F[i-1]);
        }
        printf("%lld\n", ans);
    }

    return 0;
} 

向前走,别回头。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值