莫比乌斯反演之随便写写...

莫比乌斯真的…难推…有时间..再推吧【捂脸】

莫比乌斯反演呢,其实说的就是

g ( n ) = d | n μ ( n d ) f ( d ) = d | n μ ( d ) f ( n d )

变下型就是
f ( k ) = x = 1 n k g ( k x ) g ( k ) = x = 1 n k f ( k x ) μ ( d )

μ 这个可以通过预处理线性时间求出
就像这样

void mobius(){
    mu[1]=1;
    memset(notprime,false,sizeof(notprime));
    for(int i=2;i<=50000;i++){
        if(!notprime[i]) prime[++top]=i,mu[i]=-1;
        for(int j=1;j<=top && prime[j]*i<=50000;j++){
            notprime[prime[j]*i]=true;
            if(i%prime[j]==0){
                mu[i*prime[j]]=0;
                break;
            }mu[i*prime[j]]=-mu[i];
        }
}

那么说个小例子吧
1 <= x <= n 1 <= y <= m ,求使 g c d ( x y ) = k 的对数 (bzoj1101/lg3455)

我们设 g ( k ) 表示 g c d ( x y ) = k 的倍数的对数, f ( k ) 表示 g c d ( x y ) = k 的对数(即所求)

g ( k ) = x = 1 n k f ( k x )

由莫比乌斯变形可以得到
f ( k ) = x = 1 n k g ( k x ) μ ( x )

又发现呢, g ( k ) 可以求(不像 f ( k ) 哼)
因为,如果 g c d ( i j ) = k i = k x 1 j = k x 2 ,所以就求有多少对 x 1 x 2 即可
x 1 x 2 都应当是k的倍数才有可能
所以
f ( k ) = x = 1 n k μ ( x ) n k x m k x
然后就可以求出来啦

当然..这个方法吧…不太适用【捂脸】..就是…不适用于大多数题
因此..还有另一个想法【捂脸】(是不是感觉很无奈 哎呀我也没办法~)
求的就是

i = 1 n j = 1 m [ g c d ( i , j ) == k ]
i = 1 n k j = 1 m k [ g c d ( i , j ) == 1 ]

也就是 g c d ( i , j ) == 1 时个数加一,就和 ε 很像哦 ε ( x ) = { 1 x = 1 0 d e f a u l t
因此所求就是
i = 1 n k j = 1 m k ε ( g c d ( i , j ) == 1 )

又因为 μ 1 = ε
i = 1 n k j = 1 m k d | g c d ( i , j ) μ ( d )

d = 1 m i n ( n k m k ) μ ( d ) n k d m k d

就是这样【捂脸】

不过呢~
还可以更好哦~
可以分块【捂脸】
因为 n k 最多 n 块, m k x 最多 m
因此把每个相等的块( n k m k 相等)..找到这个块中对应的 μ 和(可通过前缀和求出)即可~

ll f(int n,int m,int k){
    if(n>m) swap(n,m);
    n/=k;m/=k;
    ll ans=0;
    for(int i=1,last=1;i<=n;i=last+1){
        last=min(n/(n/i),m/(m/i));
        ans+=(ll)(mu[last]-mu[i-1])*(m/i)*(n/i);
    }return ans;
}

扩展一下,a<=x<=b,c<=y<=d的时候呢

做法就是用容斥原理【捂脸】
结果就是 f ( b , d , k ) f ( a 1 , d , k ) f ( b , c 1 , k ) + f ( a 1 , c 1 , k )


小女子不才,欢迎大佬们找错【捂脸】

猜你喜欢

转载自blog.csdn.net/sunshiness_s/article/details/80178689
今日推荐