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[1] = sum[1] = 1;
    for(int i = 2; i <= N; i++){
    if(!notprime[i]) mu[i] = -1, prime[++tot] = i;
    for(int j = 1; j <= tot && i * prime[j] <= N; j++){
        notprime[i * prime[j]] = 1;
        if(i % prime[j]) mu[i * prime[j]] = -mu[i];
        else{
        mu[i * prime[j]] = 0;
        break;
        }
    }
    sum[i] = sum[i - 1] + mu[i];
    }
}
int main()
{
    getmu();
    scanf("%d",&T);
    while (T--)
    {
    scanf("%d%d%d",&a,&b,&d),a/=d,b/=d,ans=0;
    if (a>b) swap(a,b);
    for (int i=1,last=0;i<=a;i=last+1)
    {
        last=min(a/(a/i),b/(b/i));
        ans+=ll(a/i)*(b/i)*(sum[last]-sum[i-1]);
    }
    printf("%lld\n",ans);
    }
    return 0;
}

 

posted @ 2018-01-05 15:17  MSPqwq  阅读(129)  评论(0编辑  收藏  举报