[51nod1585]卖邮票送邮票

来源:互联网 发布:批发衣服软件 编辑:程序博客网 时间:2024/05/22 04:47

Description

给出n个数,问有多少种先选择一个数,再选择任意个数的方法满足:后选出来的数的gcd不为1,但所有数的gcd为1
n<=5*1e5 2<=ai<=1e7

Solution

这道题和之前某次NOIP模拟的T3有点像,不过那道题是给出选择的那个数。。
那么我们还是枚举gcd,如果gcd为一个质数p,那么所有p的倍数选择起来,再任意选择一个其他的数就一定满足条件
但是这样发现对于两个质数p和q,pq会被算重,要减掉。。。
依次类推,直接容斥,发现容斥系数为莫比乌斯函数的相反数
复杂度O(AlogA)

Solution

#include <cstdio>#include <cstring>#include <algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)using namespace std;typedef long long ll;const int N=1e7,Mo=1e9+7;int cnt[N+5],mu[N+5],p[N],two[N],ans,n;bool bz[N+5];int read() {    char ch;    for(ch=getchar();ch<'0'||ch>'9';ch=getchar());    int x=ch-'0';    for(ch=getchar();ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';    return x;}void get_mu() {    fo(i,2,N) {        if (!bz[i]) p[++p[0]]=i,mu[i]=-1;        fo(j,1,p[0]) {            int k=i*p[j];if (k>N) break;            bz[k]=1;if (!(i%p[j])) break;            mu[k]=-mu[i];        }    }}int main() {    n=read();    fo(i,1,n) cnt[read()]++;    get_mu();    two[0]=1;fo(i,1,n) two[i]=(two[i-1]<<1)%Mo;    int ans=0;    fo(i,2,N)        if (mu[i]) {            int x=0;            fo(j,1,N/i) x+=cnt[i*j];            if (mu[i]==-1) (ans+=(ll)(n-x)*(two[x]-1)%Mo)%=Mo;            else (ans+=Mo-(ll)(n-x)*(two[x]-1)%Mo)%=Mo;        }    printf("%d\n",ans);}
原创粉丝点击