bzoj5332/loj2565 [Sdoi2018]旧试题(Mobius反演+图论)

x=1Ay=1Bz=1Cd(xyz) ∑ x = 1 A ∑ y = 1 B ∑ z = 1 C d ( x y z )
类似这道题的结论,我们有
d(xyz)=i|xj|yk|z[(i,j)==1][(j,k)==1][(i,k)==1] d ( x y z ) = ∑ i | x ∑ j | y ∑ k | z [ ( i , j ) == 1 ] [ ( j , k ) == 1 ] [ ( i , k ) == 1 ]
于是带进去,就是求

x=1Ay=1Bz=1Ci|xj|yk|z[(i,j)==1][(j,k)==1][(i,k)==1] ∑ x = 1 A ∑ y = 1 B ∑ z = 1 C ∑ i | x ∑ j | y ∑ k | z [ ( i , j ) == 1 ] [ ( j , k ) == 1 ] [ ( i , k ) == 1 ]

i=1Aj=1Bk=1C[(i,j)==1][(j,k)==1][(i,k)==1]AiBjCk ∑ i = 1 A ∑ j = 1 B ∑ k = 1 C [ ( i , j ) == 1 ] [ ( j , k ) == 1 ] [ ( i , k ) == 1 ] ⌊ A i ⌋ ⌊ B j ⌋ ⌊ C k ⌋

莫比乌斯反演一下就是:

i=1Aj=1Bk=1Cu|iu|jμ(u)v|jv|kμ(v)w|iw|kμ(w)AiBjCk ∑ i = 1 A ∑ j = 1 B ∑ k = 1 C ∑ u | i ∧ u | j μ ( u ) ∑ v | j ∧ v | k μ ( v ) ∑ w | i ∧ w | k μ ( w ) ⌊ A i ⌋ ⌊ B j ⌋ ⌊ C k ⌋

u=1Av=1Bw=1Cμ(u)μ(v)μ(w)u|iw|iAiu|jv|jBjv|kw|kCk ∑ u = 1 A ∑ v = 1 B ∑ w = 1 C μ ( u ) μ ( v ) μ ( w ) ∑ u | i ∧ w | i ⌊ A i ⌋ ∑ u | j ∧ v | j ⌊ B j ⌋ ∑ v | k ∧ w | k ⌊ C k ⌋

fx(n)=n|dxd f x ( n ) = ∑ n | d ⌊ x d ⌋ ,这个东西显然可以nlogn预处理
Ans=u=1Av=1Bw=1Cμ(u)μ(v)μ(w)fA(lcm(u,w))fB(lcm(u,v))fC(lcm(v,w)) A n s = ∑ u = 1 A ∑ v = 1 B ∑ w = 1 C μ ( u ) μ ( v ) μ ( w ) f A ( l c m ( u , w ) ) f B ( l c m ( u , v ) ) f C ( l c m ( v , w ) )

我们注意到若n>x,那么 fx(n)=0 f x ( n ) = 0
令n=max(A,B,C)
那么只有当lcm(x,y)<=n时 fx(n) f x ( n ) 才有值。
因此我们对mu[x]!=0的点x建无向图。如果lcm(x,y)<=n就建边,边权为lcm(x,y)
对于所有三元环算贡献即可。建图要枚举lcm来建… O(nlog2n) O ( n l o g 2 n )
这样的话点数最多60794,边数最多760741.
但是你需要优美的枚举三元环才能通(卡)过!

比如去掉自环,把非三个不同点构成的三元环在外面枚举了。
比如ans最后再取模,不会爆ll。
比如给边定向,把无向图变成有向图。(度数小的向度数大的连边,这样才可以保证复杂度 O(mm) O ( m m )
这样的话一个三元环只会被枚举到一次,即你枚举了无序三元组,你需要把六种情况全都统计了。
然后你枚举一个点x,再枚举一个它的出点y,再枚举一个出点z就好啦。

复杂度大概 O((nlog2n)1.5) O ( ∑ ( n l o g 2 n ) 1.5 )

#include 
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
#define mod 1000000007
#define pa pair
inline char gc(){
    static char buf[1<<16],*S,*T;
    if(T==S){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=gc();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x*f;
}
int n,prime[N>>3],tot=0,mu[N],m,du[N];
ll fa[N],fb[N],fc[N],sa[N],sb[N],sc[N],ans=0;
bool notprime[N];
struct E{
    int u,v,w;
    bool cmp(){return du[u]20];
vectoreg[N];
inline void add(int x,int y,int w){eg[x].push_back(make_pair(y,w));}
inline int gcd(int x,int y){return y?gcd(y,x%y):x;}
inline void init(){
    notprime[1]=1;mu[1]=1;
    for(int i=2;i<=1e5;++i){
        if(!notprime[i]) prime[++tot]=i,mu[i]=-1;
        for(int j=1;prime[j]*i<=1e5;++j){
            notprime[prime[j]*i]=1;
            if(i%prime[j]==0){
                mu[prime[j]*i]=0;break;
            }mu[prime[j]*i]=-mu[i];
        }
    }
}
int main(){
//  freopen("a.in","r",stdin);
    int tst=read();init();
    while(tst--){
        int A=read(),B=read(),C=read();n=max(A,max(B,C));m=0;ans=0;
        for(int i=1;i<=n;++i)
            for(int j=i;j<=n;j+=i)
                fa[i]+=A/j,fb[i]+=B/j,fc[i]+=C/j;
        for(int i=1;i<=n;++i) ans+=mu[i]*mu[i]*mu[i]*fa[i]*fb[i]*fc[i];
        for(int i=1;i<=n;++i)
            for(int j=1;i*j<=n;++j){
                if(!mu[i*j]) continue;
                for(int k=1;i*j*k<=n;++k){
                    if(!mu[i*k]||k==j||gcd(j,k)!=1) continue;
                    int u=i*j,v=i*k,w=i*j*k,tmp=mu[u]*mu[u]*mu[v];
                    ans+=tmp*fa[u]*fb[w]*fc[w];
                    ans+=tmp*fb[u]*fa[w]*fc[w];
                    ans+=tmp*fc[u]*fa[w]*fb[w];
                    if(kcontinue;e[++m].u=u;e[m].v=v;e[m].w=w;
                    du[u]++;du[v]++;
                }
            }
        for(int i=1;i<=m;++i) if(e[i].cmp()) add(e[i].u,e[i].v,e[i].w);
        else add(e[i].v,e[i].u,e[i].w);
        for(int x=1;x<=n;++x){
            for(int i=0;iint y=eg[x][i].first,w=eg[x][i].second;
                sa[y]=fa[w];sb[y]=fb[w];sc[y]=fc[w];
            }for(int i=0;iint y=eg[x][i].first,w1=eg[x][i].second;
                for(int j=0;jint z=eg[y][j].first,w2=eg[y][j].second;
                    int tmp=mu[x]*mu[y]*mu[z];
                    ans+=tmp*fa[w1]*fb[w2]*sc[z];
                    ans+=tmp*fa[w1]*sb[z]*fc[w2];
                    ans+=tmp*fa[w2]*fb[w1]*sc[z];
                    ans+=tmp*fa[w2]*sb[z]*fc[w1];
                    ans+=tmp*sa[z]*fb[w1]*fc[w2];
                    ans+=tmp*sa[z]*fb[w2]*fc[w1];
                }
            }for(int i=0;iint y=eg[x][i].first,w=eg[x][i].second;
                sa[y]=sb[y]=sc[y]=0;
            }
        }printf("%lld\n",ans%mod);
        for(int i=1;i<=n;++i) fa[i]=fb[i]=fc[i]=0,eg[i].clear(),du[i]=0;
    }return 0;
}

你可能感兴趣的:(bzoj,莫比乌斯反演)