您的位置:首页 > 其它

bzoj 2820 YY的GCD 莫比乌斯反演

2015-09-06 21:02 441 查看
题目大意:

给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对

这里就抄一下别人的推断过程了



后面这个g(x) 算的方法就是在线性筛的时候只考虑当前的数最小因子,如果进来的最小因子不存在,相当于在之前那个数的基础上的每个mu值都多加了一个质数,那么

这些mu值就要取反,如果已经包含了这个最小因子,我这里另外进行了跟之前类似的讨论方法,在代码中写着

因为这题目数据比较大,这里求解的时候不应该线性求,因为总是有一段区间的n/i*(m/i)值相同,将g[]数组求一个前缀和,记录一段区间得到的值,可以缩小到

sqrt(n)的复杂度

/*bzoj2820 YY的GCD*/
#include <bits/stdc++.h>

using namespace std;
#define ll long long
#define N 10000000
int mu[N+5] , prime[N+5] , tot , f[N+5] , sum[N+5];
bool check[N+5];

void get_mu()
{
mu[1] = 1;
for(int i=2 ; i<=N ; i++){
if(!check[i]){
prime[tot++] = i;
mu[i] = -1;
f[i] = 1;
}
for(int j=0 ; j<tot ; j++){
if((ll)prime[j]*i>N) break;
check[prime[j]*i] = true;
if(i%prime[j]){
mu[i*prime[j]] = -mu[i];
f[i*prime[j]] = -f[i]+mu[i];
}else{
/*
本身i中已经含有素数prime[j]
在if中表示含有至少3个因子prime[j],那么最后不管怎么样,当前数值除以一个因子都至少
含有两个prime[j],那么必然为0
else 只有2个prime[j]的情况,那么就是除了除以prime[j]其他情况得到的都是至少有两个因子
的,那么mu[]必然为0,而因为从当前增加了一个因子,那么就是讲那个取到的取反就可以了
*/
if((i/prime[j])%prime[j]==0) f[i*prime[j]] = mu[i];
else f[i*prime[j]] = -mu[i/prime[j]];
break;
}
}
}
for(int i=1 ; i<=N ; i++) sum[i] = sum[i-1]+f[i];
}
int n , m;

ll solve()
{
int mn = min(n , m) , last ;
ll ret=0;
for(int i=1 ; i<=mn ; i=last+1){
last = min(n/(n/i) , m/(m/i));
ret += (ll)(sum[last]-sum[i-1])*(n/i)*(m/i);
}
return ret;
}

int main()
{
freopen("in.txt" , "r" , stdin);
get_mu();
int T;
scanf("%d" , &T);
while(T--){
scanf("%d%d" , &n , &m);
printf("%lld\n" , solve());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: