日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

BZOJ 2820 莫比乌斯反演

發布時間:2025/7/14 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BZOJ 2820 莫比乌斯反演 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

思路:

$\Sigma_{i=1}^n\Sigma_{j=1}^mgcd(i,j)==p(p是素數)$


$\Sigma_{p是素數}^{p<=n}\Sigma_{i=1}^{\lfloor \frac{n}{p} \rfloor}\Sigma_{j=1}^{\lfloor \frac{m}{p} \rfloor}gcd(i,j)==1$


由$e=μ|1$可得$gcd(i,j)==1 等價于 \Sigma_{d|gcd(i,j)} μ(d)$


所以原式為


$\Sigma_{p是素數}^{p<=n}\Sigma_{i=1}^{\lfloor \frac{n}{p} \rfloor}\Sigma_{j=1}^{\lfloor \frac{m}{p}\rfloor}\Sigma_{d|gcd(i,j)}μ(d)$


$\Sigma_{p是素數}^{p<=n}\Sigma_{i=1}^{\lfloor \frac{n}{p} \rfloor}\Sigma_{j=1}^{\lfloor \frac{m}{p}\rfloor}\Sigma_{d|i且d|j}μ(d)$


$\Sigma_{p是素數}^{p<=n}\Sigma_{d=1}^{\frac{n}{p}}\lfloor{\frac{n}{pd}}\rfloor\lfloor{\frac{m}{pd}}\rfloor μ(d)$


設$k=pd$


$\Sigma_{k=1}^{min(n,m)}\lfloor{\frac{n}{k}}\rfloor\lfloor{\frac{m}{k}}\rfloor\Sigma_{p|k}μ(\frac{k}{p})$

?

設$g(x)=\Sigma_{p|k}μ(\frac{k}{p})$


可以預處理g(x)


怎么求g(x)呢


有兩種方法


1.暴力枚舉


枚舉素數 p


用$μ(p)$更新$μ(i*p)(i*p<=max(n,m))$


這樣素數有$n/logn$個


枚舉i的均攤復雜度是$O(logn)$的


乘起來就是$O(n)$了


2.
線性篩

對于素數p g(p)=1(顯然)

?

由于$μ(x)_{x的因子有平方項}=0$


所以$prime[j]|i$的時候$g(i*prime[j])$的結果就是$μ(i)$了


因為我們求的是$\Sigma_{p|k}μ(\frac{k}{p})$而且$μ(x)$是積性函數


那我們不妨設$i*prime[j]=k$


設$P$是包含$prime[j]$的所有素數 $p$是不包含$prime[j]$的所有素數


$\Sigma_{P|k}μ(\frac{k}{P})=\Sigma_{P|k}μ(\frac{i*prime[j]}{P})$


$=\Sigma(μ(\frac{i}{p})*μ(prime[j]))+μ\frac{(i*prime[j])}{prime[j]}$


$=μ(prime[j])*g[i]+μ(i)=-g[i]+μ(i)$

?

處理完了g(x)


原式就是這個樣子的$\Sigma_{k=1}^{min(n,m)}\lfloor{\frac{n}{k}}\rfloor\lfloor{\frac{m}{k}}\rfloor g(k)$


對于g(k)搞個前綴和


$\lfloor{\frac{n}{k}}\rfloor\lfloor{\frac{m}{k}}\rfloor$這個東西可以分塊

?


終于搞完了
喜聞樂見
吼吼

枚舉素數的

//By SiriusRen #include <cstdio> #include <algorithm> using namespace std; const int maxn=10000005; #define int long long int cases,n,m,mu[maxn],p[maxn],sum[maxn],f[maxn],tot; long long ans;bool vis[maxn]; signed main(){mu[1]=1;for(int i=2;i<maxn;i++){if(!vis[i])p[++tot]=i,mu[i]=-1;for(int j=1;j<=tot&&i*p[j]<maxn;j++){mu[i*p[j]]=-mu[i],vis[i*p[j]]=1;if(!(i%p[j])){mu[i*p[j]]=0;break;}}}for(int i=1;i<=tot;i++)for(int j=1;j*p[i]<maxn;j++)f[j*p[i]]+=mu[j];for(int i=1;i<maxn;i++)f[i]+=f[i-1];scanf("%d",&cases);while(cases--){scanf("%d%d",&n,&m),ans=0;if(n>m)swap(n,m);for(int i=1,j;i<=n;i=j+1){j=min(n/(n/i),m/(m/i));ans+=(f[j]-f[i-1])*(n/i)*(m/i);}printf("%lld\n",ans);} }

這是線性篩的

//By SiriusRen #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int N=10000005; int T,prime[N],vis[N],mu[N],tot,n,m;ll f[N],ans; int main(){mu[1]=1;for(int i=2;i<N;i++){if(!vis[i])prime[++tot]=i,mu[i]=-1,f[i]=1;for(int j=1;i*prime[j]<N&&j<=tot;j++){vis[i*prime[j]]=1,mu[i*prime[j]]=-mu[i],f[i*prime[j]]=-f[i]+mu[i]; if(i%prime[j]==0){mu[i*prime[j]]=0;f[i*prime[j]]=mu[i];break;}}f[i]+=f[i-1];}scanf("%d",&T);while(T--){scanf("%d%d",&n,&m),ans=0;for(int l=1,r;l<=min(n,m);l=r+1){r=min(n/(n/l),m/(m/l));ans+=1ll*(f[r]-f[l-1])*(n/l)*(m/l);}printf("%lld\n",ans);} }

?

轉載于:https://www.cnblogs.com/SiriusRen/p/6680518.html

總結

以上是生活随笔為你收集整理的BZOJ 2820 莫比乌斯反演的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。