• BZOJ 2820: YY的GCD 莫比乌斯反演 + 数学推导 + 线性筛


    求 $sum_{i=1}^{n}sum_{j=1}^{m}[gcd(i,j)in prime]$
     
    按套路前提 $gcd(i,j)$
     
    $Rightarrowsum_{d=1}^{n}din primesum_{i=1}^{n}sum_{j=1}^{m}[gcd(i,j)==d]$
     
    后面的 $sum_{i=1}^{n}sum_{j=1}^{m}[gcd(i,j)==d]$ 是反演模板
     
    $Rightarrow sum_{b=1}^{left lfloor frac{n}{d} ight floor}mu(b)left lfloor frac{n}{db} ight floor left lfloor frac{m}{db} ight floor$
     
    答案为 $sum_{d=1}^{n}din prime sum_{b=1}^{left lfloor frac{n}{d} ight floor}mu(b)left lfloor frac{n}{db} ight floor left lfloor frac{m}{db} ight floor$
     
    用这个式子整除分块算是 $O(n)$ 的,我们优化一下.
     
    令 $T=db$
     
    则原式 $=sum_{T=1}^{n}left lfloor frac{n}{T} ight floorleft lfloor frac{m}{T} ight floorsum_{d|T,din prime}mu(frac{T}{d})$
     
    发现后面的 $sum_{d|T,din prime}mu(frac{T}{d})$ 可以提前预处理(只需枚举质数并暴力更新就行)
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <vector> 
    #define maxn 10000009
    const long long N = 10000009 ; 
    #define ll long long 
    #define setIO(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)  
    using namespace std; 
    int vis[maxn],prime[maxn],mu[maxn],g[maxn],tot; 
    long long sumv[maxn]; 
    void init(){
        mu[1]=1; 
        for(int i=2;i<maxn;++i) {
            if(!vis[i]) { prime[++tot]=i,mu[i]=-1; }
            for(int j=1;j<=tot && (ll)prime[j]*i < (ll)maxn;++j) 
            {
                vis[prime[j]*i]=1; 
                if(i % prime[j]==0) {
                    mu[i * prime[j]]=0; 
                    break; 
                }
                mu[i * prime[j]]=-mu[i]; 
            }
        } 
        for(int i=1;i<=tot;++i)
            for(ll j=1;(ll)j*prime[i]<N;++j) 
                g[prime[i]*j]+=mu[j];
        for(int i=1;i<=10000000;++i) sumv[i] = (long long)sumv[i-1]+g[i]; 
    }
    ll work(int n,int m) {
        if(n>m) swap(n,m); 
        long long ans=0; 
        for(ll i=1,j;i<=n;i=j+1) {
            j = min(n/(n/i),m/(m/i)); 
            ans += (n/i) * (m/i) * (sumv[j] - sumv[i-1]); 
        }
        return ans; 
    }
    int main(){
        //setIO("input");
        init();  
        int T,x,y; scanf("%d",&T);
        while(T--) scanf("%d%d",&x,&y),printf("%lld
    ",work(x,y));  
        return 0; 
    }
    

      

  • 相关阅读:
    java 之 xml
    oracle 之 定时任务,存储过程和游标等语法案例
    oracle 之创建定时器
    java 之 音乐播放代码
    oracle函数之 minus
    iis默认文档有什么用?
    html页面使用前端框架布局时,弹出子页面等情况若出现布局混乱,可能是回发导致
    html 之 区块元素属性(待补充)
    EffectiveJava(2)应对多个构造函数应当使用构建器
    EffectiveJava(1) 构造器和静态工厂方法
  • 原文地址:https://www.cnblogs.com/guangheli/p/10439342.html
Copyright © 2020-2023  润新知