HDU5514 容斥原理
每次遇到容斥,都只会直接上莫比乌斯系数,方便快捷,这次1e9的GG了,实际上还是容斥,只不过这次并不需要很多数的容斥,只需要m的因子之间互相容斥一下就可以了。
参考一份题解很不错,他文中提到的错误解法我们队训练时也这么想的。。http://m.blog.csdn.net/kevin66654/article/details/52724774
1 #include <bits/stdc++.h> 2 const long long mod = 1e9+7; 3 const double ex = 1e-10; 4 #define inf 0x3f3f3f3f 5 using namespace std; 6 long long tmp[11234]; 7 long long tmp2[11234]; 8 long long p[112342]; 9 int tt[112342]; 10 long long gcd(long long x,long long y){ 11 return y==0?x:gcd(y,x%y); 12 } 13 int main() 14 { 15 int T; 16 scanf("%d",&T); 17 for (int cas = 1 ; cas <= T; cas++){ 18 int n; 19 long long m; 20 scanf("%d%lld",&n,&m); 21 22 for (int i = 1; i<=n; i++){ 23 scanf("%lld",&tmp[i]); 24 tmp[i] = gcd(tmp[i],m); 25 } 26 sort(tmp+1,tmp+1+n); 27 if (tmp[1]==1){ 28 printf("Case #%d: %lld\n",cas,m*(m-1)/2); 29 continue; 30 } 31 int cnt = 0; 32 for (int i = 1 ; i<=n ;i++){ 33 int flag = 1; 34 for (int j = 1; j<i ; j++){ 35 if (tmp[i] % tmp[j] == 0 ) { 36 flag = 0; 37 break; 38 } 39 } 40 if (flag)tmp2[++cnt] = tmp[i]; 41 } 42 tmp2[cnt+1] = mod; 43 int cntt = 0; 44 for (int i = 2 ; i*i<=m; i++){ 45 if (m%i==0) { 46 p[++cntt] = i; 47 if (i*i!=m) p[++cntt] = m/i; 48 } 49 } 50 memset(tt,0,sizeof(tt)); 51 sort(p+1,p+cntt+1); 52 int pos = 1; 53 long long ans = 0; 54 for (int i = 1; i<=cntt ; i++){ 55 if (tmp2[pos] == p[i]) ans += (m/tmp2[pos])*(m/tmp2[pos]-1)/2*tmp2[pos],pos++,tt[i] = 1; 56 else{ 57 int flag = 1; 58 for (int j = 1; tmp2[j] < p[i] ; j++){ 59 if (p[i] % tmp2[j]==0) {flag = 0;break;} 60 } 61 if (flag) continue; 62 int t = 0; 63 for (int j = 1; j < i ; j++){ 64 if (p[i] % p[j] == 0) {t+=tt[j];} 65 } 66 ans += (1-t) * (m/p[i])*(m/p[i]-1)/2*p[i] , tt[i]=(1-t); 67 } 68 } 69 printf("Case #%d: %lld\n",cas,ans); 70 } 71 return 0; 72 }