51Nod1192 Gcd表中的质数

105 篇文章 0 订阅
57 篇文章 0 订阅


题目看这里
又到了推式子的时候了,莫比乌斯反演入门题

i=1nj=1m[prime(i,j)] ∑ i = 1 n ∑ j = 1 m [ p r i m e ( i , j ) ]

首先搞一个 f(d) f ( d ) 表示有多少对(i,j)的gcd就是d
那么原式 =nd=1[prime(d)]f(d) = ∑ d = 1 n [ p r i m e ( d ) ] ∗ f ( d )
F(x)=x|df(d)=[nx][mx] F ( x ) = ∑ x | d f ( d ) = [ n x ] [ m x ]
就得到原式 =nd=1[prime(d)]iF(id)μ(i) = ∑ d = 1 n [ p r i m e ( d ) ] ∗ ∑ i F ( i ∗ d ) ∗ μ ( i )
=id<=nF(id)μ(i)[prime(d)] = ∑ i ∗ d <= n F ( i ∗ d ) ∗ μ ( i ) ∗ [ p r i m e ( d ) ]
=T<=nF(T)prime(d)=1,d|Tμ(Td) = ∑ T <= n F ( T ) ∗ ∑ p r i m e ( d ) = 1 , d | T μ ( T d )
预处理后面那个 g(T)=prime(d)=1,d|Tμ(Td) g ( T ) = ∑ p r i m e ( d ) = 1 , d | T μ ( T d ) 就可以分块求答案了

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 5000010
#define LL long long
using namespace std;
bool vis[N];
int mu[N],s[N],w[N>>2],t,n,m,T;
inline LL F(int d){
    return (LL)(n/d)*(m/d);
}
inline void cal(){
    scanf("%d%d",&n,&m);
    if(n>m) swap(n,m); LL S=0;
    for(int i=1,j;i<=n;i=j+1){
        j=min(n/(n/i),m/(m/i));
        S+=F(i)*(s[j]-s[i-1]);
    }
    printf("%lld\n",S);
}
int main(){
    mu[1]=1;
    for(int i=2;i<=5000000;++i){
        if(!vis[i]) mu[w[++t]=i]=-1;
        for(int j=1,k;j<=t && (k=i*w[j])<=5000000;++j){
            vis[k]=1;
            if(i%w[j]==0) { mu[k]=0; break; } else mu[k]=-mu[i];
        }
    }
    for(int i=1;i<=t;++i)
        for(int j=w[i],k=1;j<=5000000;++k,j+=w[i]) s[j]+=mu[k];
    for(int i=1;i<=5000000;++i) s[i]+=s[i-1];
    for(scanf("%d",&T);T--;cal());
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值