【BZOJ2820】GCD

博客介绍了BZOJ2820题目的解决方案,利用莫比乌斯反演进行求解,并通过设置辅助变量dp优化时间复杂度,以应对多组数据的挑战。最后提供了AC代码,总时间复杂度为O(T⋅(π(n)logπ(n)+n))。
摘要由CSDN通过智能技术生成
题目

链接:BZOJ2820
(权限题,洛谷P2257

解法:莫比乌斯反演

一道较简单的莫比乌斯反演,推推式子就OK了。

Ans=i=1nj=1mp[gcd(i,j)=p]=pinpjmp[gcd(i,j)=1]=pinpjmpd|gcd(i,j)μ(d)=pd=1min(np,mp)μ(d)indpjmdp1=pd=1min(np,mp)ndpmdpμ(d) A n s = ∑ i = 1 n ∑ j = 1 m ∑ p [ gcd ( i , j ) = p ] = ∑ p ∑ i ⌊ n p ⌋ ∑ j ⌊ m p ⌋ [ gcd ( i , j ) = 1 ] = ∑ p ∑ i ⌊ n p ⌋ ∑ j ⌊ m p ⌋ ∑ d | gcd ( i , j ) μ ( d ) = ∑ p ∑ d = 1 min ( ⌊ n p ⌋ , ⌊ m p ⌋ ) μ ( d ) ∑ i ⌊ n d p ⌋ ∑ j ⌊ m d p ⌋ 1 = ∑ p ∑ d = 1 min ( ⌊ n p ⌋ , ⌊ m p ⌋ ) ⌊ n d p ⌋ ⌊ m d p ⌋ μ ( d )

单次询问时间复杂度: O(π(n)min(n,m)) O ( π ( n ) min ( n , m ) ) ,一眼看过去,诶,能过,突然就看到了多组数据 T105 T ⩽ 10 5 。。凉了呀

发现式中有迭代变量的乘积,于是设 t=dp t = d p ,就有:

Ans=pd=1min(np,mp)ndpmdpμ(d)=t=dpntmtpμ(tp) A n s = ∑ p ∑ d = 1 min ( ⌊ n p ⌋ , ⌊ m p ⌋ ) ⌊ n d p ⌋ ⌊ m d p ⌋ μ ( d ) = ∑ t = d p ⌊ n t ⌋ ⌊ m t ⌋ ∑ p μ ( t p )

在筛出素数后,迭代求出 pμ(tp) ∑ p μ ( t p ) 的前缀和,
即可使用分块求解。

时间复杂度: O(T(π(n)logπ(n)+n)) O ( T ⋅ ( π ( n ) log ⁡ π ( n ) + n ) )

AC代码
#include<iostream>
#include<cstdio>
#include<vector>

using namespace std;

const int N=10000000;
vector<int> prime;
bool check[10000001];
int T,n,m;
long long summu[10000001],mu[10000001];

void sieve(){
    mu[1]=1ll;
    for(int i=2;i<=N;++i){
        if(!check[i])prime.push_back(i),mu[i]=-1ll;
        for(int j:prime){
            if(i*j>N)break;
            mu[i*j]=-mu[i],check[i*j]=true;
            if(i%j==0){mu[i*j]=0;break;}
        }
    }
    for(int i:prime)for(int j=1;i*j<=N;++j)summu[i*j]+=mu[j];
    for(int i=1;i<=N;++i)summu[i]+=summu[i-1];
}

void solve(int n,int m){
    if(n>m)swap(n,m);
    int lst;long long res=0ll;
    for(int i=1;i<=n;i=lst+1)lst=min(n/(n/i),m/(m/i)),res+=(summu[lst]-summu[i-1])*(n/i)*(m/i);
    printf("%lld\n",res);
}

int main(){
    sieve();
    scanf("%d",&T);for(int i=1;i<=T;++i)scanf("%d%d",&n,&m),solve(n,m);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值