HDU 6053 TrickGCD(莫比乌斯反演)
http://acm.hdu.edu.cn/showproblem.php?pid=6053
题意:
给出一个A数组,B数组满足Bi<=Ai。
现在要使得这个B数组的GCD值>=2,求共有多少种情况。
思路:
在比赛的时候筛了素数表,然后枚举GCD来做,但是还是有些重复情况无办法剔除,赛后才知道是要用莫比乌斯来处理的,然后就趁机学习了一下莫比乌斯。
先是枚举GCD,每个数的可选情况就是GCD/a【i】,在这里我们可以把GCD/a【i】相同的数一起处理,也就是用快速幂来计算,这样会显得更快。
那么莫比乌斯是用来干嘛的呢?
然后就是容斥思想。
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 = 1e5 + 5; 17 18 const int mod= 1e9+7; 19 20 int n; 21 int a[maxn]; 22 23 ll cnt[maxn]; 24 ll num[3*maxn]; 25 26 bool check[maxn+1000]; 27 int prime[maxn+1000]; 28 int mu[maxn+1000]; 29 30 void Moblus() 31 { 32 memset(check,false,sizeof(check)); 33 mu[1] = 1; 34 int tot = 0; 35 for(int i = 2; i <= maxn; i++) 36 { 37 if( !check[i] ){ 38 prime[tot++] = i; 39 mu[i] = -1; 40 } 41 for(int j = 0; j < tot; j++) 42 { 43 if(i * prime[j] > maxn) break; 44 check[i * prime[j]] = true; 45 if( i % prime[j] == 0){ 46 mu[i * prime[j]] = 0; 47 break; 48 }else{ 49 mu[i * prime[j]] = -mu[i]; 50 } 51 } 52 } 53 } 54 55 ll qpow(ll a, ll b) 56 { 57 ll ans=1; 58 while(b) 59 { 60 if(b&1) ans=(ans*a)%mod; 61 a=(a*a)%mod; 62 b>>=1; 63 } 64 return ans; 65 } 66 67 int main() 68 { 69 //freopen("in.txt","r",stdin); 70 Moblus(); 71 int kase=0; 72 int T; 73 scanf("%d",&T); 74 while(T--) 75 { 76 memset(cnt,0,sizeof(cnt)); 77 scanf("%d",&n); 78 int MIN=INF; 79 int MAX=0; 80 for(int i=1;i<=n;i++) 81 { 82 scanf("%d",&a[i]); 83 MIN=min(MIN,a[i]); 84 MAX=max(MAX,a[i]); 85 cnt[a[i]]++; 86 } 87 88 num[0]=0; 89 for(int i=1;i<=200000;i++) num[i]=num[i-1]+cnt[i]; 90 91 ll ans=0; 92 93 for(int i=2;i<=MIN;i++) 94 { 95 ll tmp=1; 96 for(int j=1;j*i<=MAX;j++) 97 { 98 tmp=(tmp*qpow((ll)j,num[i*j+i-1]-num[i*j-1]))%mod; //快速幂计算,j是GCD的倍数,也就是a【i】/GCD 99 } 100 ans=(ans-tmp*mu[i]+mod)%mod; 101 } 102 103 printf("Case #%d: %I64d\n",++kase,ans); 104 } 105 return 0; 106 }