51nod 1585 买邮票送邮票

版权声明:原来这里可以拿来卖萌ヽ(・∀・)ノ https://blog.csdn.net/u012345506/article/details/86547178

考虑枚举买哪一张,那么买第 i i 张产生的贡献为:
j a i μ ( j ) x x ( S a i ) g c d ( x ) > 1 [ j g c d ( x , a i ) ] \sum_{j|a_i}\mu(j)\sum_{x\neq \emptyset \land x\subset (S-a_i)\land gcd(x)>1}[j|gcd(x,a_i)]
注意到当 j > 1 j>1 时,后面那一串时等价于:
x x ( S a i ) [ j g c d ( x , a i ) ] = 2 ( k = 1 n [ j a k ] 1 ) 1 1 \sum_{x\neq \emptyset \land x\subset (S-a_i)}[j|gcd(x,a_i)]\\ =2^{(\sum_{k=1}^n[j|a_k]1)-1}-1
所以我们只需要分析 j = 1 j=1 时的情况,此时我们需要求出 x x ( S a i ) g c d ( x ) > 1 1 \sum_{x\neq \emptyset \land x\subset (S-a_i)\land gcd(x)>1}1 ,即不包含 a i a_i g c d > 1 gcd>1 的集合总数。
容易想到其和 x x S g c d ( x ) > 1 1 \sum_{x\neq \emptyset \land x\subset S\land gcd(x)>1}1 可以在 O ( a i ) O(\sqrt {a_i}) 间转换:
x x S g c d ( x ) > 1 1 = 2 n 1 ( j = 1 n μ ( j ) ( 2 k = 1 n [ i a k ] 1 1 ) ) \sum_{x\neq \emptyset \land x\subset S\land gcd(x)>1}1\\ =2^n-1-(\sum_{j=1}^n\mu(j)(2^{\sum_{k=1}^n[i|a_k]1}-1))
只需要将 2 n 2^n 改为 2 n 1 2^{n-1} ,同时将 a i a_i 的因数产生的贡献消去即可。

这么做计算最终结果产生的复杂度应当为 O ( 1 0 7 l o g 1 0 7 ) O(10^7log10^7) ,为了优化,对于因数,可以只计算 μ ( i ) 0 \mu(i)\neq 0 的部分,当 a i 1 0 7 a_i\le 10^7 时,这么做在最坏的情况下产生的因子数只有 2 e 7 2e7 不到。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<climits>
#include<cstdio>
#include<cmath>
using namespace std;
#define clr(a) memset(a,0,sizeof(a))
//--Container
//--
typedef long long ll;
const ll md=1e9+7;
const int up=1e7;
int pr[up+10],mp[up+10];bool bd[up+10];int mu[up+10],pn,n;

void _sie(){
    int i,j,k,d,t;for(pn=0,mu[1]=1,i=2;i<=up;++i){
        if(!bd[i])pr[++pn]=i,mu[i]=-1,mp[i]=i;
        for(j=1;j<=pn&&(ll)pr[j]*i<=up;++j){
            bd[pr[j]*i]=1,mu[pr[j]*i]=-mu[i],mp[pr[j]*i]=pr[j];
            if(!(i%pr[j])){
                mu[pr[j]*i]=0;
                break;
            }
        }
    }
    for(i=1;i<=up;++i)if(mu[i]<0)mu[i]+=md;
};
int _shak(int n,int*cr,int*crn){
    int i,j,k,d,r=1,t,zs[40],zn=0;for(;n>1;){
        if(cr)zs[zn++]=mp[n];
        r*=mp[n],t=mp[n];for(;mp[n]==t;n/=mp[n]);
    }
    if(cr){
        for(i=0;i<(1<<zn);++i){
            for(d=1,j=0;j<zn;++j)if(i&(1<<j))d*=zs[j];
            cr[i]=d;
        }
        *crn=i;
    }
    return r;
};

int sm[up+10],_2p[500010],ccr[10010];ll drs;
void _init(){
    int i;for(_2p[0]=1,i=1;i<=500000;++i)_2p[i]=(_2p[i-1]+_2p[i-1])%md;
};
void _upd(int n){
    int i,j,k,d,r=_shak(n,ccr,&d);
    for(i=0;i<d;++i)sm[ccr[i]]++;
};
void _drs(){
    int i,j;for(i=1;i<=up;++i)if(mu[i]!=0)drs=(drs+(ll)mu[i]*(md-1+_2p[sm[i]])%md)%md;
};
ll _cl(int x,ll drs){
    ll rs=0;int i,j,k,d,t=_shak(x,ccr,&d);
    for(i=0;i<d;++i){
        drs=(drs+md-(ll)mu[ccr[i]]*(md-1+_2p[sm[ccr[i]]])%md)%md;
        drs=(drs+(ll)mu[ccr[i]]*(md-1+_2p[sm[ccr[i]]-1])%md)%md;
    }
    drs=(md+_2p[n-1]-1-drs)%md;
    for(i=1;i<d;++i){
        drs=(drs+(ll)mu[ccr[i]]*(md-1+_2p[sm[ccr[i]]-1]))%md;
    }
    return drs;
};
int ar[500010];
void cl(){
    int i,j,k,d,t;ll rs=0;scanf("%d",&n);for(i=1;i<=n;scanf("%d",&ar[i++]));
    for(i=1;i<=n;_upd(ar[i++]));drs=0;_drs();for(i=1;i<=n;++i){
        rs=(rs+_cl(ar[i],drs))%md;
    }
    printf("%lld\n",rs);
};

int main(){
#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif
    _sie();_init();cl();
    return 0;
};

猜你喜欢

转载自blog.csdn.net/u012345506/article/details/86547178
今日推荐