hdu 1695 GCD(莫比乌斯反演+分块模板)

https://blog.sengxian.com/algorithms/mobius-inversion-formula

公式:

约数形式

F(n)=d|nf(d)f(n)=d|nμ(d)F(nd)=d|nμ(nd)F(d) F ( n ) = ∑ d | n f ( d ) ⟺ f ( n ) = ∑ d | n μ ( d ) F ( n d ) = ∑ d | n μ ( n d ) F ( d )

F(n)=d=1nif(id)f(n)=d=1niμ(d)F(id) F ( n ) = ∑ d = 1 ⌊ n i ⌋ f ( i ⋅ d ) ⟺ f ( n ) = ∑ d = 1 ⌊ n i ⌋ μ ( d ) F ( i ⋅ d )

倍数形式

F(n)=n|df(d)f(n)=n|dμ(dn)F(d) F ( n ) = ∑ n | d f ( d ) ⟺ f ( n ) = ∑ n | d μ ( d n ) F ( d )

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn=100010;
LL T,b,d,k,ans1,ans2;

int prime[maxn],Pcnt,mu[maxn],sum[maxn];
bool del[maxn];
void mobius(){
    sum[1]=mu[1]=1;
    for(int i=2;i<maxn;i++){
        if(!del[i]) prime[++Pcnt]=i,mu[i]=-1;
        for(int j=1,p;j<=Pcnt&&(p=i*prime[j])<maxn;j++){
            del[p]=1;
            if(i%prime[j]==0){mu[p]=0; break;}
            mu[p]=-mu[i];
        }
        sum[i]=sum[i-1]+mu[i];
    }
}

inline LL solve(LL n,LL m,LL D){
    LL ret=0;
    for(int i=1,nxt;i<=n;i=nxt+1){
        nxt=min(n/(n/i),m/(m/i));
        ret+=(sum[nxt]-sum[i-1])*(n/i)*(m/i);
    }
    return ret;
}

int main(){
    scanf("%lld",&T);
    mobius();
    for(int Case=1;Case<=T;Case++){
        ans1=ans2=0;
        scanf("%lld%lld%lld%lld%lld",&b,&b,&d,&d,&k);
        if(b>d) swap(b,d);
        if(k==0) {printf("Case %d: 0\n",Case); continue;}
        b/=k,d/=k;
        printf("Case %d: %lld\n",Case,solve(b,d,k)-solve(b,b,k)/2);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值