【POJ3904】Sky Code [数学 莫比乌斯反演 入门]

POJ - 3904

大概 好像 只用到了那个思想  只是这道题用的素数筛和我常用的不一样 然后就 emmmmmm

把mo[prime[j]*i]打成了mo[i] 然后就是prime[j]*i<N打成了prime[j]<N/i 好像是精度有问题

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<queue>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<stack>
 7 #include<algorithm>
 8 using namespace std;
 9 #define ll long long
10 #define rg register
11 const int N=10000+5,inf=0x3f3f3f3f,P=19650827;
12 int n,num[N],cnt[N],mx;
13 template <class t>void rd(t &x)
14 {
15     x=0;int w=0;char ch=0;
16     while(!isdigit(ch)) w|=ch=='-',ch=getchar();
17     while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
18     x=w?-x:x;
19 }
20  
21 int mo[N],tot=0,prime[N];
22 bool v[N];
23 void mobius()
24 {
25     tot=0,mo[1]=1;
26     memset(v,0,sizeof(v));
27     for(rg int i=2;i<N;++i)
28     {
29         if(!v[i]) prime[++tot]=i,mo[i]=-1;
30         for(rg int j=1;j<=tot&&prime[j]*i<N;++j)
31         {
32             v[prime[j]*i]=1;
33             if(i%prime[j]) mo[prime[j]*i]=-mo[i];
34             else {mo[prime[j]*i]=0;break;}
35         }
36     }
37 }
38  
39 ll solve()
40 {
41     ll ans=0;
42     for(rg int i=1;i<=mx;++i)
43     for(rg int j=i;j<=mx;j+=i)
44     cnt[i]+=num[j];
45     for(rg int i=1;i<=mx;++i)
46     {
47         int x=cnt[i];
48         if(x>=4) ans+=(ll)mo[i]*(x-1)*(x-2)*(x-3)*x/24;
49     }
50     return ans;
51 }
52  
53 void clean()
54 {
55     memset(num,0,sizeof(num));
56     memset(cnt,0,sizeof(cnt));
57     mx=0;
58 }
59  
60 int main()
61 {
62     //freopen("in.txt","r",stdin);
63     //freopen("nocows.out","w",stdout);
64     mobius();
65     while(scanf("%d",&n)==1)
66     {
67         clean();
68         int x;
69         for(rg int i=1;i<=n;++i) rd(x),++num[x],mx=max(mx,x);
70         printf("%lld
",solve());
71     }
72     return 0;
73 }
原文地址:https://www.cnblogs.com/lxyyyy/p/10916201.html