码迷,mamicode.com
首页 > 其他好文 > 详细

莫比乌斯反演呓语

时间:2018-08-14 14:30:33      阅读:95      评论:0      收藏:0      [点我收藏+]

标签:break   org   false   return   highlight   code   分享   bit   com   

技术分享图片

技术分享图片

接下来介绍一种线性筛的做法来筛出莫比乌斯函数。 
if (i % p[j] == 0)这句话非常关键,也是为什么这个筛法是线性筛的原因。 
同样把这个程序的μ[x]μ[x] 去掉就是单纯的质数筛,同样这个质数筛由于if (i % p[j] == 0) 的存在,也是一个线性筛。

void mobius()
{
    int i,j; mbs[1] = 1;
    fo(i,2,N)
        {
            if (!vis[i]) {p[++p[0]] = i; mbs[i] = -1;}
            for (j = 1;j <= p[0] && i * p[j] <= N; j++)
                {
                    vis[i*p[j]] = 1;
                    if (i % p[j] == 0) {mbs[i*p[j]] = 0; break;}
                    mbs[i*p[j]] = - mbs[i];
                }
        }
}

  技术分享图片

#include <bits/stdc++.h>
using namespace std;

const int MAXN = 100000;
bool check[MAXN+10];
int prime[MAXN+10];
int mu[MAXN+10];

//求1-n,1-m内gcd=x(的倍数)的个数,修改可以改这个(大概,我还没试过)
inline long long f(int n,int m,int x){
    return (n/x)*(m/x);
}


void Moblus()
{
    memset(check,false,sizeof(check));
    mu[1] = 1;
    int tot = 0;
    for(int i = 2; i <= MAXN; i++)
    {
        if( !check[i] )
        {
            prime[tot++] = i;
            mu[i] = -1;
        }
        for(int j = 0; j < tot; j ++)
        {
            if( i * prime[j] > MAXN) break;
            check[i * prime[j]] = true;
            if( i % prime[j] == 0)
            {
                mu[i * prime[j]] = 0;
                break;
            }
            else
            {
                mu[i * prime[j]] = -mu[i];
            }
        }
    }
}
int sum[MAXN+10];


//找[1,n],[1,m]内互质的数的对数
long long solve(int n,int m)
{
    long long ans = 0;
    if(n > m)swap(n,m);
    for(int i = 1, la = 0; i <= n; i = la+1)
    {
        la = min(n/(n/i),m/(m/i));
        ans += (long long)(sum[la] - sum[i-1])*f(n,m,i);
    }
    return ans;

}
int main()
{
    Moblus();
    sum[0] = 0;
    for(int i = 1; i <= MAXN; i++)   sum[i] = sum[i-1] + mu[i];
    int a,b,c,d,k;
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
        long long ans = solve(b/k,d/k) - solve((a-1)/k,d/k) - solve(b/k,(c-1)/k) + solve((a-1)/k,(c-1)/k);
        printf("%lld\n",ans);
    }
    return 0;
}

 

莫比乌斯反演呓语

标签:break   org   false   return   highlight   code   分享   bit   com   

原文地址:https://www.cnblogs.com/bestefforts/p/9473771.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!