1 5 1 3 9 10 2
4
题目大意
给定n个数,求在其中选定三个数,三个数全部互质或者互相全部不互质的组数
解题思路
现场想到莫比乌斯没有出……模型没有建立好……
首先想到所有可能的出现的组数是C(n,3)组
而类似红蓝三角形的做法便是枚举出和特定的数互质与不互质的数的个数,乘积和cn待处理
与某一个特定的数互质的数的数量可以通过容斥或者莫比乌斯反演求出(所有其约数的倍数之个数*约数对应的mu值)
而每个数的倍数的个数可以通过nlgn的复杂度求出
而对于每一个不符合要求的三角形,三组数之中一定有两组互质一组不互质,或者一组互质两组不互质,会被重复计算两次,答案即C(n,3)-cn/2;
code:
#include <cstdio> #include <iostream> #include <algorithm> #include <ctime> #include <cctype> #include <cmath> #include <string> #include <cstring> #include <stack> #include <queue> #include <list> #include <vector> #include <map> #include <set> #define sqr(x) ((x)*(x)) #define LL long long #define INF 0x3f3f3f3f #define PI acos(-1.0) #define eps 1e-10 using namespace std; int mul[100005]; int mu[100005]; int cnt[100005]; int a[100005]; int cop[100005]; int com[100005]; int pri[100005],pn=0; int main() { memset(com,0,sizeof com); mu[1]=1; for (int i=2;i<=100000;i++) { if (com[i]==0) { pri[++pn]=i; mu[i]=-1; } for (int j=1;j<=pn&&pri[j]*i<=100000;j++) { if (i%pri[j]) { mu[i*pri[j]]=-mu[i]; com[i*pri[j]]=1; } else { mu[i*pri[j]]=0; com[i*pri[j]]=1; break; } } } int T; scanf("%d",&T); while (T--) { int n; scanf("%d",&n); memset(cnt,0,sizeof cnt); memset(mul,0,sizeof mul); memset(cop,0,sizeof cop); for (int i=1;i<=n;i++) { scanf("%d",&a[i]); cnt[a[i]]++; } for (int i=1;i<=100000;i++) for (int j=i;j<=100000;j+=i) mul[i]+=cnt[j]; for (int i=1;i<=100000;i++) for (int j=i;j<=100000;j+=i) cop[j]+=mu[i]*mul[i]; long long ans=(long long)n*(n-1)*(n-2)/6; // printf("%lld\n",ans); long long cn=0; for (int i=1;i<=n;i++) { if (a[i]==1) continue; cn+=(long long)cop[a[i]]*(long long)(n-1-cop[a[i]]); if ((long long)cop[a[i]]*(long long)(n-1-cop[a[i]])<0) printf("QUQ"); } // printf("%I64d\n",ans); // printf("%I64d\n",cn); ans-=cn/2; printf("%I64d\n",ans); } return 0; } ;