/** 题目:hdu6053 TrickGCD 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6053 题意:You are given an array A , and Zhu wants to know there are how many different array B satisfy the following conditions? * 1≤Bi≤Ai * For each pair( l , r ) (1≤l≤r≤n) , gcd(bl,bl+1...br)≥2 思路:枚举2<=gcd<=misA; misA表示A数组最小的数。 当gcd==2. 贡献为: (a1/2)*(a2/2)*...*(an/2);所有2的倍数的组合。 当gcd==3. 贡献为: (a1/3)*(a2/3)*...*(an/3);所有3的倍数的组合。 当gcd==4.不需要计算因为在2中算过了。 。 。 gcd==6. 减去。因为2,3都算过6,所以多算了一次。 也就是按照容斥原理的做法。 如果gcd可以被一个素数的平方整除,那么该gcd不用计算。 否则:f(i) = (-1)^(k+1); k表示i这个数的素因子个数。 由于mu[i] = (-1)^k; 所以求mu之后取反。 对于确定的gcd==2,计算贡献:因为ai/2很多结果相同。[gcd,2*gcd)范围内的数/gcd的结果都是1,[2*gcd,3*gcd)范围内的数/gcd的结果都是2.。。。 所以贡献等于1^num1 * 2^num2 * 3^num3 ... (numi表示结果为1的数量。可以利用前缀和统计范围内的数。) 其他类比。 */ #include <cstdio> #include <cstring> #include <algorithm> #include <set> #include <iostream> #include <vector> using namespace std; typedef long long LL; #define ms(x,y) memset(x,y,sizeof x) typedef pair<int, int> P; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; const int maxn = 1e5 + 1000; vector<P> gd;///value, num; int sum[maxn]; int vis[maxn], mu[maxn]; int prime[maxn], cnt; void init()///莫比乌斯 { memset(vis,0,sizeof(vis)); mu[1] = 1; cnt = 0; for(int i=2; i<maxn; i++) { if(!vis[i]) { prime[cnt++] = i; mu[i] = -1; } for(int j=0; j<cnt&&i*prime[j]<maxn; j++) { vis[i*prime[j]] = 1; if(i%prime[j]) mu[i*prime[j]] = -mu[i]; else { mu[i*prime[j]] = 0; break; } } } for(int i = 2; i < maxn; i++){ if(mu[i]!=0){ gd.push_back(P(i,-mu[i])); } } } LL Pow(LL x, int y) { LL p = 1; while (y) { if (y & 1) p = p*x%mod; x = x*x%mod; y >>= 1; } return p; } int main() { int T, cas = 1; int n; init(); cin >> T; while (T--) { scanf("%d", &n); ms(sum, 0); int x, misx = INF; for (int i = 0; i < n; i++) { scanf("%d", &x); misx = min(misx, x); sum[x]++; } for (int i = 1; i < maxn; i++) { sum[i] += sum[i - 1]; } LL ans = 0; int len = gd.size(); for (int i = 0; i < len&&gd[i].first <= misx; i++) { int gcd = gd[i].first; LL cnt = 1; for (int j = gcd; j < maxn; j += gcd) { cnt = cnt*Pow(j / gcd, sum[min(maxn - 1, j + gcd - 1)] - sum[j - 1]) % mod; } ans = (ans + cnt*gd[i].second + mod) % mod; //cout<<"gcd = "<<gcd<<endl; //cout<<"ans = "<<ans<<endl; } //cout<<"ans = "<<ans<<endl; printf("Case #%d: %lld ", cas++, ans); } return 0; }