首页 > 代码库 > hdu5072 容斥+枚举
hdu5072 容斥+枚举
这题说的是给了 n 个数字 每个数值大于1 小于100000,n小于100000 ,找出满足下面要求的三人组有多少种 比如abc ( (ab)==(bc)==(ac) ==1 )||( (ab)!=1&&(bc)!=1&&(ac)!=1 )
(()----表示gcd )计算出这样的三元组的个数。
这样考虑 三元组必须满足上面的要求 , 那么我们减去不满足的可能情况 abc 计算与 a互质的个数 和与a不互质的个数 得到了b在内的不可行的方案数,然后这样发现会多算一次 如果abc
(ab)==1 (ac)!=1 在计算c的时候又会计算一次。 然后我们得到了所有的 不肯能方案除以2 得到了不可能的方案数 总方案数减去不可能方案数就得到了(因为数比较小用容斥便可以计算出答案)
#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#include<string.h>#include <vector>using namespace std;typedef pair<int,int> PF;bool vis[100005];int prime[10000],num;void pri_p(){ num=0; memset(vis,false,sizeof(vis)); for(long long i=2; i<=100000; ++i) if(vis[i]==false){ prime[num++]=i; for(long long j=i*i; j<=100000; j+=i) vis[j]=true; }}int A[100005];int P[15];int sizea[100005];int D[100005];vector<PF>F[100005];void fenjie(int loc,int len){ for(int s=1; s<(1<<len); ++s){ int ss=1,num=0; for(int i=0;i<len ;++i){ if(s&(1<<i)){ ss*=P[i]; num++; } } F[loc].push_back(make_pair(ss,num)); } sizea[loc]=F[loc].size();}void inti(){ pri_p(); for(int i=1; i<=100000; ++i){ int len=0; int s=i,num=0; while(s>1&&prime[num]!=0){ if(s%prime[num]==0){ P[len++]=prime[num]; while(s>1&&s%prime[num]==0){ s/=prime[num]; } } num++; } fenjie(i,len); }}void sum(int loc){ int sz=sizea[loc]; for(int i=0; i<sz; ++i){ PF t=F[loc][i]; D[t.first]++; }}int jud(int loc){ int ans=0; for(int i=0; i<sizea[loc]; ++i){ PF f=F[loc][i]; if(f.second%2==1)ans+=D[f.first]; else ans-=D[f.first]; } return ans;}int main(){ inti(); int cas; scanf("%d",&cas); for(int cc=1; cc<=cas; ++cc){ long long n; scanf("%I64d",&n); memset(D,0,sizeof(D)); for(int i=0; i<n; ++i){ scanf("%d",&A[i]); sum(A[i]); } long long ans=0; for(int i=0; i<n; ++i){ long long S= jud(A[i]); long long noeven = n-S; if(S<=1||noeven==0) continue; ans = ans+noeven*(S-1); } printf("%I64d\n",n*(n-1)*(n-2)/6-ans/2); } return 0;}
hdu5072 容斥+枚举
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。