1. 程式人生 > >P2257 YY的GCD(莫比烏斯反演)

P2257 YY的GCD(莫比烏斯反演)

cstring ctype ... space problem get pct pre div

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\n",ans); }return 0; }

P2257 YY的GCD(莫比烏斯反演)