zoukankan      html  css  js  c++  java
  • PGCD2

    这题肝了三四天,其他啥也没做...

    传送门

    然后...双倍经验

    简单版

    不知道为什么会脑抽去帮 LZ_101 大佬验题...

    题目和被 A 穿的 PGCD 一样,数据范围变成大概 2e11 ...

    于是我们就要考虑用更加优秀的做法去解决这道题了

    首先我们得想到 PGCD 中最优秀的解法:

    [ANS=sum_{i=1}^{n} lfloor {nover d} floor lfloor {mover d} floor sum_{p∈ prime ,p|d} mu({pover d}) ]

    这里我们令 (sum(d)=sum_{p∈ prime ,p|d} mu({pover d})) ,那么这个东西可以在线性筛中预处理出来,具体方法看代码中线性筛处理部分

    然后我们考虑数论分块时要能够 O(1) 得到这个 sum 的前缀和,那么我们发现这个函数不是积性函数(况且你能找到一个合适的 g 来和它卷积么),于是不能用杜教筛求解

    那么我们自然想到可以处理非积性函数的 min_25 筛了

    我们先 min_25 预处理出素数个数的前缀和

    然后第二部分中一遍处理 Mu 的信息,一遍处理 Sum ,也就是需要求的答案

    那么我们令 (Sum(n,j)) 表示 n 以内最小质因子大于等于 (p_j) 或是 质数的 sum 函数的前缀和,令 (Mu(n,j)) 表示 n 以内最小质因子大于等于 (p_j) 的 mu 函数的前缀和,然后转移就是:

    [Sum(n,j)=Sum(n,j+1)+Mu({nover p_j},j+1)-Sum({nover p_j},j+1)+2* j +({nover p_j^{~~ 2}}<=p_j~ ?~ Mu({nover p_j^{~~ 2}},j+1)+j ~:~ 0) ]

    [Mu(n,j)=Mu(n,j+1)+Mu({nover p_j},j+1)+j ]

    最后我们处理出来的所有 (Sum(n,1)) 就是数论分块里面要用到的 sum 的前缀和了

    学过 min_25 的人都知道为什么这样推导吧...

    code

    代码... 人傻常数大.jpg

    //by Judge
    #include<bits/stdc++.h>
    #include<unordered_map>
    #define Rg register
    #define fp(i,a,b) for(Rg int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(Rg int i=(a),I=(b)-1;i>I;--i)
    #define III __int128
    #define ll long long
    using namespace std;
    const int M=1e7+3;
    typedef int arr[M];
    typedef ll ARR[M];
    #ifndef Judge
    #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    #endif
    char buf[1<<21],*p1=buf,*p2=buf;
    template<class T>inline T Min(T a,T b){return a<b?a:b;}
    template<class T>inline bool cmax(T& a,T b){return a<b?a=b,1:0;}
    inline ll read(){ ll x=0,f=1; char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    	for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
    } char sr[1<<21],z[21];int CCF=-1,Z;
    inline void Ot(){fwrite(sr,1,CCF+1,stdout),CCF=-1;}
    inline void print(III x,char chr='
    '){
        if(CCF>1<<20)Ot();if(x<0)sr[++CCF]=45,x=-x;
        while(z[++Z]=x%10+48,x/=10);
        while(sr[++CCF]=z[Z],--Z);sr[++CCF]=chr;
    } ll n,m,MX,sq,cnt; III ans; arr v,p,id1,id2;
    ARR w,h,mu,sum,S; III Sum[M],Mu[M]; unordered_map<ll,III> ANS;
    inline void prep_sum(ll n){ mu[1]=1;
    	fp(i,2,n){ if(!v[i]) p[++cnt]=i,mu[i]=-1,sum[i]=1;
    		for(int j=1,k;j<=cnt&&p[j]*i<=n;++j){ v[k=i*p[j]]=1;
    			if(!(i%p[j])){ sum[k]=mu[i]; break; }
    			mu[k]=-mu[i],sum[k]=mu[i]-sum[i];
    		} S[i]=sum[i],sum[i]+=sum[i-1];
    	}
    }
    inline int ID(Rg ll x){return x<=sq?id1[x]:id2[n/x];}
    inline void prep_num(ll N){ if(N<=MX) return ;
    	sq=sqrt(n=N),m=0; int tot=upper_bound(p+1,p+1+cnt,sq)-p-1;
    	for(Rg ll l=1;l<=n;l=w[m]+1) w[++m]=n/(n/l),h[m]=w[m]-1,w[m]<=sq?id1[w[m]]=m:id2[n/w[m]]=m;
    	fp(j,1,tot) for(Rg int i=m;i&&1ll*p[j]*p[j]<=w[i];--i) h[i]-=h[ID(w[i]/p[j])]-j+1;
    	fp(i,1,m) Mu[i]=-h[i],Sum[i]=h[i];
    	fd(j,tot,1) for(Rg int i=m,k,kk;i&&1ll*p[j]*p[j]<=w[i];--i) k=ID(w[i]/p[j]),kk=ID(w[k]/p[j]),
    		Sum[i]+=Mu[k]-Sum[k]+(j<<1)-(w[kk]>=p[j]?Mu[kk]+j:0)-1,Mu[i]-=Mu[k]+j;
    	fp(i,1,m) ANS[w[i]]=Sum[i];
    }
    inline III GET(Rg ll n){ return n<=MX?sum[n]:ANS[n];}
    #define swap(x,y) (x)^=(y)^=(x)^=(y)
    int main(){ int T=read(); prep_sum(MX=1e7);
    	fp(i,1,T){ Rg ll n=read(),m=read(),bl;
    		if(n>m) swap(n,m); ans=0,ANS.clear(),prep_num(n),prep_num(m);
    		for(Rg ll l=1,r;l<=n;l=r+1) r=Min(n/(n/l),m/(m/l)),
    			ans+=(GET(r)-GET(l-1))*(n/l)*(m/l); print(ans);
    	} return Ot(),0;
    }
    
  • 相关阅读:
    陶瓷电容的结构、工艺、失效模式
    Vue.js最佳实践
    Vue 超快速学习
    CSS 小技巧
    HTML5 Canvas
    webkit下面的CSS设置滚动条
    Some untracked working tree files would be overwritten by checkout. Please move or remove them before you can checkout. View them
    JSCS: Please specify path to 'JSCS' package
    React中ref的使用方法
    React 60S倒计时
  • 原文地址:https://www.cnblogs.com/Judge/p/10695339.html
Copyright © 2011-2022 走看看