Description
求有多少对(x,y)的gcd为素数,x<=n,y<=m。n,m<=1e7,T<=1e4。
Solution
因为题目要求gcd为素数的,那么我们就只考虑素数mu的贡献就行了
对于p,对于k*p的贡献是mu[k]
然后加上整除分块优化就行了
p可以筛完素数处理,处理复杂度为O(n/log*log)正好为O(n)
Code
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #define ll long long 5 using namespace std; 6 7 const int maxn=1e7+5; 8 9 int flag[maxn],prime[maxn],mu[maxn],cnt; 10 ll sum[maxn]; 11 int n,m; 12 13 void getmu(){ 14 mu[1]=1; 15 for(int i=2;i<=1e7;i++){ 16 if(!flag[i]){ 17 prime[++cnt]=i; 18 mu[i]=-1; 19 } 20 for(int j=1;i*prime[j]<=1e7&&j<=cnt;j++){ 21 flag[i*prime[j]]=1; 22 if(i%prime[j]==0){ 23 mu[i*prime[j]]=0; 24 break; 25 } 26 mu[i*prime[j]]=-mu[i]; 27 } 28 } 29 for(int i=1;i<=cnt;i++) 30 for(int j=prime[i];j<=1e7;j+=prime[i]) 31 sum[j]+=mu[j/prime[i]]; 32 for(int i=1;i<=1e7;i++) 33 sum[i]+=sum[i-1]; 34 } 35 36 int main(){ 37 getmu(); 38 int T; 39 scanf("%d",&T); 40 while(T--){ 41 scanf("%d%d",&n,&m); 42 if(n>m) swap(n,m); 43 ll ans=0; 44 for(int i=1,pos=1;i<=n;i=pos+1){ 45 pos=min(n/(n/i),m/(m/i)); 46 ans+=(sum[pos]-sum[i-1])*(n/i)*(m/i); 47 } 48 printf("%lld\n",ans); 49 } 50 return 0; 51 }
时间: 2024-10-19 07:07:18