1. 程式人生 > >SPOJ - PGCD Primes in GCD Table(莫比烏斯反演)

SPOJ - PGCD Primes in GCD Table(莫比烏斯反演)

cnblogs -s def problems 前綴和 ret mage () eof

http://www.spoj.com/problems/PGCD/en/

題意:

給出a,b區間,求該區間內滿足gcd(x,y)=質數的個數。

思路:

設f(n)為 gcd(x,y)=p的個數,那麽F(n)為 p | gcd(x,y)的個數,顯然可得F(n)=(x/p)*(y/p)。

這道題目因為可以是不同的質數,所以需要枚舉質數,技術分享

但是這樣枚舉太耗時,所以在這裏令t=pk,

技術分享

這樣一來的話,我們只需要預處理u(t/p)的前綴和,之後像之前的題一樣分塊處理就可以了。

 1 #include<iostream>
 2 #include<algorithm>
 3
#include<cstring> 4 #include<cstdio> 5 #include<sstream> 6 #include<vector> 7 #include<stack> 8 #include<queue> 9 #include<cmath> 10 #include<map> 11 #include<set> 12 using namespace std; 13 typedef long long ll; 14 typedef pair<int
,int> pll; 15 const int INF = 0x3f3f3f3f; 16 const int maxn = 1e7 + 100; 17 18 int a, b; 19 20 bool check[maxn]; 21 int prime[maxn]; 22 int mu[maxn]; 23 ll sum[maxn]; 24 25 void Mobius() 26 { 27 memset(check, false, sizeof(check)); 28 mu[1] = 1; 29 int tot = 0; 30 for
(int i = 2; i <= maxn; i++) 31 { 32 if (!check[i]) 33 { 34 prime[tot++] = i; 35 mu[i] = -1; 36 } 37 for (int j = 0; j < tot; j++) 38 { 39 if (i * prime[j] > maxn) 40 { 41 break; 42 } 43 check[i * prime[j]] = true; 44 if (i % prime[j] == 0) 45 { 46 mu[i * prime[j]] = 0; 47 break; 48 } 49 else 50 { 51 mu[i * prime[j]] = -mu[i]; 52 } 53 } 54 } 55 56 sum[0]=0; 57 for(int i=0;i<tot;i++) 58 { 59 for(int j=prime[i];j<maxn;j+=prime[i]) 60 { 61 sum[j]+=mu[j/prime[i]]; 62 } 63 } 64 for(int i=1;i<maxn;i++) 65 sum[i]+=sum[i-1]; 66 return ; 67 } 68 69 ll solve(int n, int m) 70 { 71 if(n>m) swap(n,m); 72 ll ans=0; 73 74 for(int i=1,last=0;i<=n;i=last+1) 75 { 76 last=min(n/(n/i),m/(m/i)); 77 ans+=(sum[last]-sum[i-1])*(n/i)*(m/i); 78 } 79 return ans; 80 } 81 82 83 int main() 84 { 85 //freopen("in.txt","r",stdin); 86 int T; 87 Mobius(); 88 89 scanf("%d",&T); 90 while(T--) 91 { 92 scanf("%d%d",&a,&b); 93 ll ans = solve(a,b); 94 printf("%lld\n",ans); 95 } 96 return 0; 97 }

SPOJ - PGCD Primes in GCD Table(莫比烏斯反演)