[BZOJ2820]YY的GCD|莫比乌斯反演
Description
神犇YY虐完数论后给傻×kAc出了一题给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对kAc这种傻×必然不会了,于是向你来请教……多组输入
题面依然很亲切,和之前不同的在于是所有质数
然后把式子化一化,对莫比乌斯函数求一个奇怪的前缀和
这里的时间复杂度比较神奇..
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 const int maxn = 10000010,maxp = 664580; 5 int vis[maxn],prime[maxp],mu[maxn]; 6 long long sum[maxn]; 7 int min(int a,int b){if (a<b) return a;else return b;} 8 void build(){ 9 memset(vis,1,sizeof(vis)); 10 prime[0]=0;mu[1]=1; 11 for (int i=2;i<=maxn;i++){ 12 if (vis[i]){ 13 prime[++prime[0]] = i; 14 mu[i] = -1; 15 } 16 for (int j=1;j<=prime[0]&&i*prime[j]<=maxn;j++){ 17 vis[i*prime[j]] = 0; 18 if (i%prime[j]==0){ 19 mu[i*prime[j]] = 0; 20 break; 21 } 22 mu[i*prime[j]] = -mu[i]; 23 } 24 } 25 memset(sum,0,sizeof(sum)); 26 for (int i=1;i<=prime[i];i++) 27 for (int j=1;j*prime[i]<=maxn;j++) sum[j*prime[i]]+=mu[j]; 28 for (int i=2;i<=maxn;i++) sum[i]+=sum[i-1]; 29 } 30 31 long long solve(int n,int m){ 32 if (n>m){int tem=n;n=m;m=tem;} 33 int las;long long ans=0; 34 for (int i=1;i<=n;i=las+1){ 35 las = min(n/(n/i),m/(m/i)); 36 ans+=(sum[las]-sum[i-1])*(long long)(n/i)*(m/i); 37 } 38 return ans; 39 } 40 int main(){ 41 build(); 42 int test,n,m; 43 scanf("%d",&test); 44 while (test--){ 45 scanf("%d%d",&n,&m); 46 printf("%lld\n",solve(n,m)); 47 } 48 }