C - Mophues HDU - 4746(莫比乌斯反演+分块)

hdu4746
题解

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL maxn=5e5+10;
LL c[maxn][20];
LL prime[maxn],vis[maxn],tot,mu[maxn],sum[maxn];
LL cnt[maxn];
LL n,m,p;
void init()
{
    tot=0;
    vis[1]=1;
    mu[1]=1;
    for(LL i=2;i<=maxn-5;i++){
        if(vis[i]==0){
            prime[++tot]=i;mu[i]=-1;
            cnt[i]=1;
        }
        for(LL j=1;j<=tot&&i*prime[j]<=maxn-5;j++){
            vis[i*prime[j]]=1;
            mu[i*prime[j]]=-mu[i];
            cnt[i*prime[j]]=cnt[i]+1;
            if(i%prime[j]==0){
                mu[i*prime[j]]=0;
                break;
            }
        }
    }
    memset(c,0,sizeof(c));
    for(LL i=1;i<=maxn-5;i++){
        for(LL j=i;j<=maxn-5;j+=i){
            c[j][cnt[i]]+=mu[j/i];
        }
    }
    for(LL i=1;i<=maxn-5;i++){
        for(LL j=1;j<=19;j++){
            c[i][j]+=c[i][j-1];
        }
    }
    for(LL i=1;i<=maxn-5;i++){
        for(LL j=0;j<=19;j++){
            c[i][j]+=c[i-1][j];
        }
    }
}
int main()
{
   init();
   int T;
   scanf("%d",&T);
   while(T--){
    scanf("%lld%lld%lld",&n,&m,&p);
    if(n>m)swap(n,m);
    if(p>19){
        printf("%lld\n",n*m);continue;
    }
    LL ans=0;
    LL r;
    for(LL l=1;l<=n;l=r+1){
        r=min(n/(n/l),m/(m/l));
        ans+=(n/l)*(m/l)*(c[r][p]-c[l-1][p]);
    }
    printf("%lld\n",ans);
   }
   return 0;
}


©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页