hdu5514 非2的次幂容斥原理

 1 /*
 2 1
 3 126 223092870
 4 210 330 390 462 510 546 570 690 714 770 798 858 910 966 1122 1155 1190 1254 1326 1330 1365 1430 1482 1518 1610 1785 1794 1870 1938 1995 2002 2090 2145 2210 2346 2415 2470 2530 2618 2622 2805 2926 2990 3003 3094 3135 3230 3315 3458 3542 3705 3795 3910 3927 4186 4370 4389 4485 4522 4641 4845 4862 5005 5187 5313 5434 5474 5865 6118 6279 6545 6555 6578 6783 7106 7293 7315 7735 8151 8211 8398 8602 8645 8855 9177 9614 9867 10166 10465 10659 11305 11362 12155 12597 12903 13585 13685 14421 14858 15249 15295 16445 17017 17043 17765 19019 20995 21505 22287 23023 24035 24871 25415 28405 29393 30107 33649 35581 37145 39767 46189 52003 55913 62491 81719 96577 
 5 */
 6 #include <cstdio>
 7 #include <queue>
 8 #include <cstring>
 9 #include <iostream>
10 #include <cstdlib>
11 #include <algorithm>
12 #include <vector>
13 #include <map>
14 #include <set>
15 #include <ctime>
16 #include <cmath>
17 #include <cctype>
18 #define N 10000
19 #define LL long long
20 #define U unsigned
21 using namespace std;
22 int cas=1,T;
23 int n,m,a[N+10],d[N+10],dn,v[N+10],c[N+10];
24 int gcd(int a,int b)
25 {
26     return b==0?a:gcd(b,a%b);
27 }
28 void fac()
29 {
30     dn=0;
31     int x=sqrt(m)+0.5;
32     for(int i=1;i<=x;i++)
33     {
34         if(m%i==0)
35         {
36             d[dn++]=i;
37             d[dn++]=m/i;
38         }
39     }
40     sort(d,d+dn);
41 }
42 int main()
43 {
44     //freopen("1.in","w",stdout);
45     //freopen("1.in","r",stdin);
46     //freopen("out1","w",stdout);
47     scanf("%d",&T);
48     while(T--)
49     {
50         memset(v,0,sizeof(v));//要走的次数
51         memset(c,0,sizeof(c));//已经走的次数
52         scanf("%d%d",&n,&m);
53         set<int>g;
54         for(int i=0;i<n;i++) { scanf("%d",a+i);g.insert(gcd(m,a[i]%m)); }
55         fac();
56         for(set<int>::iterator it=g.begin();it!=g.end();it++)        //初始化,*it的倍数约数都要走一次
57         {
58             for(int j=0;j<dn;j++) if(d[j]% *it==0) v[j]=1;
59         }
60         LL ans=0;
61         //for(int i=0;i<dn;i++) printf("%d ",d[i]);printf("\n");
62         for(int i=0;i<dn;i++)
63         {
64             if(v[i])
65             {
66                 int dif=v[i]-c[i];        //d[i]本来要走的次数-已经走了的次数=现在要走的次数
67                 ans+=(LL)m*(m/d[i]-1)/2*dif;
68                 for(int j=i+1;j<dn;j++) if(d[j]%d[i]==0) c[j]+=dif;//d[i]走过之后d[i]的倍数也已经走了dif次,所以c[j]+=dif
69             }
70         }
71         printf("Case #%d: %lld\n",cas++,ans);
72     }
73     //printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
74     return 0;
75 }
View Code

 

posted @ 2016-04-07 23:34  cdongyang  阅读(209)  评论(0编辑  收藏  举报