zoukankan      html  css  js  c++  java
  • P2257 YY的GCD(莫比乌斯反演)

    P2257 YY的GCD

    luogu题解第一篇非常棒,当然你也可以point here(转)

    正题因为题解写的太优秀所以没得补充

    这里用了一个卡常技巧:循环展开

    就是以代码长度为代价减少循环次数

    实测快了15ms(一个点1.5ms....)

    (用了快读更慢???(大雾)但是register真有用)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #define re register
    using namespace std;
    template<typename T>T min(T &a,T &b){return a<b?a:b;}
    #define N 10000001
    typedef long long ll;
    int t,n,m,pct,pri[N],mu[N],g[N];
    ll sum[N],ans; bool v[N];
    int main(){
        mu[1]=1;
        for(re int i=2;i<N;++i){
            if(!v[i]) pri[++pct]=i,mu[i]=-1;
            for(re int j=1;j<=pct;++j){
                int tmp=i*pri[j];
                if(tmp>=N) break;
                v[tmp]=1;
                if(i%pri[j]) mu[tmp]=-mu[i];
                else break;
            }
        }//线性筛莫比乌斯函数
        for(re int i=1;i<=pct;++i)
            for(re int j=1;1ll*j*pri[i]<N;++j)
                g[j*pri[i]]+=mu[j]; //这个数的莫比乌斯函数之和
        re int u; //循环展开:累计前缀和
        for(u=1;u+4<N;u+=4){
            sum[u]=sum[u-1]+g[u];
            sum[u+1]=sum[u]+g[u+1];
            sum[u+2]=sum[u+1]+g[u+2];
            sum[u+3]=sum[u+2]+g[u+3];
        }
        for(;u<N;++u) sum[u]=sum[u-1]+g[u];
        scanf("%d",&t);
        while(t--){
            scanf("%d%d",&n,&m);
            if(n>m) swap(n,m);
            ans=0;
            for(re int l=1,r;l<=n;l=r+1){//整除分块
                r=min(n/(n/l),m/(m/l));
                ans+=1ll*(n/l)*(m/l)*(sum[r]-sum[l-1]);
            }printf("%lld
    ",ans);
        }return 0;
    }
  • 相关阅读:
    HZNU 2019 Summer training 6
    HZNU 2019 Summer training 5
    HZNU 2019 Summer training 4
    Garlands CodeForces
    HZNU 2019 Summer training 3
    UVA
    HZNU 2019 Summer training 2
    Serge and Dining Room(线段树)
    HZNU 2019 Summer training 1
    【7-10 PAT】树的遍历
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/9790153.html
Copyright © 2011-2022 走看看