标签:property seve travel integer class common ber 多少 efi
Input
Output
Sample Input
4 2 3 4 5 4 2 4 6 8 7 2 3 4 5 7 6 8
Sample Output
1 0 34
题意:给了你n个数,让你从中选出四个求出gcd(a,b,c,d)=1的对数
思路:莫比乌斯反演
首先莫比乌斯反演有两种形式,
反演公式一 f(n) = 累加(d|n) mu(d)*F(n/d)
反演公式二 f(n) = 累加(n|d) mu(d/n)*F(d)
我们设 F(n)为 gcd(a,b,c,d)==n的倍数 的对数
我们设 f(n)为 gcd(a,b,c,d)==n 的对数
那我们就是要求f(1),那就相当于 f(1) = 累加(1-n)mu(d)*F(d)
F(n) 即我求出所有数中有多少个是n个倍数即可,然后求出C(m,4)即是答案
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<iostream> #define maxn 100005 #define mod 1000000007 using namespace std; typedef long long ll; ll n; ll mu[maxn+10]; ll vis[maxn+10]; ll a[maxn+10]; ll tot[maxn+10]; void init(){ for(int i=0;i<maxn;i++){ vis[i]=0; mu[i]=1; } for(int i=2;i<maxn;i++){ if(vis[i]==0){ mu[i]=-1; for(int j=2*i;j<maxn;j+=i){ vis[j]=1; if((j/i)%i==0) mu[j]=0; else mu[j]*=-1; } } } } void get(){ for(int i=0;i<n;i++){ ll x=a[i]; ll t=sqrt(x); for(int j=1;j<=t;j++){ if(x%j==0){ tot[j]++; if(x/j!=j) tot[x/j]++; } } } } ll C(ll x){ if(x==0) return 0; return x*(x-1)*(x-2)*(x-3)/24; } int main(){ init(); while(scanf("%lld",&n)!=EOF){ memset(tot,0,sizeof(tot)); for(int i=0;i<n;i++){ scanf("%lld",&a[i]); } get(); ll sum=0; for(int i=1;i<=maxn;i++){ sum+=mu[i]*C(tot[i]); } printf("%lld\n",sum); } return 0; }
标签:property seve travel integer class common ber 多少 efi
原文地址:https://www.cnblogs.com/Lis-/p/11180001.html