【洛谷P2257】YY的GCD
阿新 • • 發佈:2019-04-16
space its return 優化 scan pri can rime play
題目大意:求\[\sum\limits_{p\in prime}\sum\limits_{i=1}^n\sum\limits_{j=1}^m[gcd(i,j)=p]\]
題解:忽略最外層的求和式,其余部分可以直接利用狄利克雷卷積+除法分塊進行計算。對於最外層的和式來說,直接枚舉素數會超時。考慮設 \(t=pd\),這樣就在兩個獨立的和式之間建立了關系,可以達到優化的作用。
代碼如下
#include <bits/stdc++.h> typedef long long ll; using namespace std; const int maxn=1e7+10; int n,m; int mu[maxn],prime[maxn],tot,f[maxn],sum[maxn]; bool vis[maxn]; void seive(){ mu[1]=1; for(int i=2;i<=1e7;i++){ if(!vis[i])prime[++tot]=i,mu[i]=-1; for(int j=1;i*prime[j]<=1e7;j++){ vis[i*prime[j]]=1; if(i%prime[j]==0)break; mu[i*prime[j]]=-mu[i]; } } for(int i=1;i<=tot;i++) for(int j=1;j*prime[i]<=1e7;j++) f[prime[i]*j]+=mu[j]; for(int i=1;i<=1e7;i++)sum[i]=sum[i-1]+f[i]; } void solve(){ ll ans=0; for(int i=1;i<=n;i++){ int j=min(n/(n/i),m/(m/i)); ans+=(ll)(sum[j]-sum[i-1])*(ll)(n/i)*(ll)(m/i); i=j; } printf("%lld\n",ans); } int main(){ seive(); int T;scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); if(n>m)swap(n,m); solve(); } return 0; }
【洛谷P2257】YY的GCD