标签:
Problem Description
题意:从一个数组中找出所有 3个数 都 相互互质 和 相互不互质 的总个数
思路:首先先转化为求 与一个数互质和不互质的个数,然后将互质和不互质相乘,然后总数减去即可。
接下来就是怎么求互质和不互质,用到了容斥原理来求,模板套一下就可以了
sum【i】数组表示i这个数是数组中的元素的因子的个数
该题还可以先求出所有的素数,范围可以自己确定,然后在分解质因数的时候可以起到优化的作用,如注释掉的部分
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 #define N 100006 6 #define ll long long 7 ll n; 8 ll a[N]; 9 //ll prime[N]; 10 //ll num[N]; 11 //ll k=0; 12 ll fac[N];//分解质因数的质因数 13 ll sum[N]; 14 ll have[N]; 15 /*void init() 16 { 17 memset(num,0,sizeof(num)); 18 for(int i=2;i<N;i++) 19 { 20 if(!num[i]) 21 { 22 prime[k++]=i; 23 for(int j=i;j<N;j+=i) 24 { 25 num[j]=1; 26 } 27 } 28 } 29 } 30 */ 31 ll solve() 32 { 33 ll ans=0; 34 for(ll i=0;i<n;i++) 35 { 36 ll m=a[i]; 37 ll num=0; 38 ll cnt=0; 39 for(ll j=2;j*j<=m;j++) 40 { 41 if(m%j==0) 42 { 43 fac[num++]=j; 44 while(m%j==0) 45 m/=j; 46 } 47 } 48 if(m>1) fac[num++]=m; 49 for(ll j=1;j<(1<<num);j++) 50 { 51 ll w=0; 52 ll tmp=1; 53 for(ll k=0;k<num;k++) 54 { 55 if((1<<k)&j) 56 { 57 tmp=tmp*fac[k]; 58 w++; 59 } 60 } 61 if(w&1) cnt+=sum[tmp]; 62 else cnt-=sum[tmp]; 63 } 64 if(cnt==0) continue; 65 ans+=(cnt-1)*(n-cnt); 66 } 67 return ans/2; 68 } 69 int main() 70 { 71 //init(); 72 int t; 73 scanf("%d",&t); 74 while(t--) 75 { 76 scanf("%I64d",&n); 77 memset(have,0,sizeof(have)); 78 memset(sum,0,sizeof(sum)); 79 80 for(ll i=0;i<n;i++) { scanf("%I64d",&a[i]); have[a[i]]=1; } 81 82 for(ll i=2;i<N;i++) 83 { 84 for(ll j=i;j<N;j+=i) 85 { 86 if(have[j]) 87 sum[i]++; 88 } 89 } 90 ll ans=n*(n-1)*(n-2)/6; 91 ans=ans-solve(); 92 printf("%I64d\n",ans); 93 } 94 return 0; 95 }
标签:
原文地址:http://www.cnblogs.com/UniqueColor/p/4734762.html