标签:prime gcd int res 容斥 mu cnt1 莫比 mod
link
题意:
长度为n的数组a,求gcd>1的子序列个数
思路:
考虑用容斥,把gcd拆成素数的乘积,先对a中的所有数都进行因子分解,然后每次计算,gcd是某个值x的倍数的方案数,那么对于任意因子p1p2p3…,我们考虑去重即可,会发现刚好是莫比乌斯的mu函数,质因子为2和以上的就不用算了,我们考虑单质因子的部分就能不重不漏的计算所有平方及以上的所有答案了,我们会发现某个数乘了一个单因子他的符号刚好就是*-1,刚好符合莫比乌斯函数的性质。如2计算了,3也计算了,那么就要去掉6的贡献。
#include<bits/stdc++.h>
#define IL inline
#define x first
#define y second
typedef long long ll;
using namespace std;
const int N=100010;
const int mod=1e9+7;
#define int long long
int qmi(int a,int b)
{
int res=1;
while(b){
if(b&1) res=res*a%mod;
b>>=1;
a=a*a%mod;
}
return res;
}
bool st[N];
int prime[N];
int cnt;
int mu[N];
int a[N];
int cnt1[N];
void init()
{
mu[1]=1;
for(int i=2;i<N;i++)
{
if(!st[i])
{
mu[i]=-1;
prime[++cnt]=i;
}
for(int j=1;j<=cnt&&i*prime[j]<N;j++)
{
st[i*prime[j]]=true;
if(i%prime[j]==0) break;
mu[i*prime[j]]=-mu[i];
}
}
}
signed main()
{
int n;
cin>>n;
init();
for(int i=1;i<=n;i++)
{
cin>>a[i];
for(int j=1;j*j<=a[i];j++)
if(a[i]%j==0)
{
cnt1[j]++;
if(j*j!=a[i])
cnt1[a[i]/j]++;
}
}
int res=0;
for(int i=2;i<=100000;i++)
{
res=(res-mu[i]*(qmi(2,cnt1[i])-1))%mod;
}
res=(res%mod+mod)%mod;
cout<<res<<endl;
return 0;
}
标签:prime,gcd,int,res,容斥,mu,cnt1,莫比,mod 来源: https://blog.csdn.net/qq_45961321/article/details/120247306
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。