njust oj triple 莫比乌斯反演

分析:令f(x)为1到n的gcd(i,j)==x的个数

           F(x)为1到n的x|gcd(i,j)的对数

          显然F(n)=∑n|df(d)

          然后由莫比乌斯反演可得f(n)=∑n|d μ(d/n)*F(d)

          由题目显然可得,令cnt=n/x,当cnt<3时,F(x)为0,cnt>=3,F(x)=cnt*(cnt-1)*(cnt-2)/6

          然后就是暴力,复杂度,O(T*n)

注:题目链接https://icpc.njust.edu.cn/Problem/Local/1923/

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;
typedef long long LL;
const int N=1e5+5;
int n,m,T,prime[N],mu[N];
bool vis[N];
void getmu()
{
    mu[1] = 1;
    int cnt = 0;
    for(int i=2; i<=N-5; i++)
    {
        if(!vis[i])
        {
            prime[cnt++] = i;
            mu[i] = -1;
        }
        for(int j=0; j<cnt&&i*prime[j]<=N-5; j++)
        {
            vis[i*prime[j]] = 1;
            if(i%prime[j]) mu[i*prime[j]] = -mu[i];
            else
            {
                mu[i*prime[j]] = 0;
                break;
            }
        }
    }
}
LL F(int x){
  LL tmp=n/x;
  if(tmp<3)return 0;
  return tmp*(tmp-1)/2*(tmp-2)/3;
}
int main(){
  getmu();
  scanf("%d",&T);
  while(T--){
    scanf("%d%d",&n,&m);
    LL ans=0;
    for(int i=1;i*m<=n;++i){
      ans+=mu[i]*F(i*m);
    }
    printf("%lld
",ans);
  }
  return 0;
}
View Code
原文地址:https://www.cnblogs.com/shuguangzw/p/5409001.html