BZOJ 1101 [POI2007]Zap | 第一道莫比乌斯反(繁)演(衍)

时间:2023-03-09 04:56:21
BZOJ 1101 [POI2007]Zap | 第一道莫比乌斯反(繁)演(衍)

题目:

http://www.lydsy.com/JudgeOnline/problem.php?id=1101


题解:

http://www.cnblogs.com/mrha/p/8203612.html

数学公式太难打了,核心思想是化成gcd(i,j)==1,然后用莫比乌斯反演变成枚举约数d,然后再搞式子

#include<cstdio>
#include<algorithm>
#define N 50005
typedef long long ll;
using namespace std;
int T,a,b,d,mu[N],prime[N],tot,sum[N];
bool notprime[N];
ll ans;
void getmu()
{
mu[] = sum[] = ;
for(int i = ; i <= N; i++){
if(!notprime[i]) mu[i] = -, prime[++tot] = i;
for(int j = ; j <= tot && i * prime[j] <= N; j++){
notprime[i * prime[j]] = ;
if(i % prime[j]) mu[i * prime[j]] = -mu[i];
else{
mu[i * prime[j]] = ;
break;
}
}
sum[i] = sum[i - ] + mu[i];
}
}
int main()
{
getmu();
scanf("%d",&T);
while (T--)
{
scanf("%d%d%d",&a,&b,&d),a/=d,b/=d,ans=;
if (a>b) swap(a,b);
for (int i=,last=;i<=a;i=last+)
{
last=min(a/(a/i),b/(b/i));
ans+=ll(a/i)*(b/i)*(sum[last]-sum[i-]);
}
printf("%lld\n",ans);
}
return ;
}