【POJ3904】Sky Code [数学 莫比乌斯反演 入门]
大概 好像 只用到了那个思想 只是这道题用的素数筛和我常用的不一样 然后就 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\n",solve()); 71 } 72 return 0; 73 }