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 }

 

posted @ 2017-10-11 15:03  HITLJR  阅读(271)  评论(0编辑  收藏  举报