莫比乌斯函数

莫比乌斯函数:

性质:

1.

2.

3.

若a,b互质,那么

[HAOI2011]Problem b

 

 

#include <bits/stdc++.h>

using namespace std;
const int N=20000;
bool vis[N+10];
int tot,prime[N+10],sum[N+10],mu[N+10];

void Mu(int n)
{
    mu[1]=1;
    for (int i=2; i<=n; i++)
    {
        if (!vis[i])
        {
            prime[++tot]=i;
            mu[i]=-1;
        }
        for (int j=1; j<=tot&&prime[j]*i<=n; j++)
        {
            vis[prime[j]*i]=1;
            if (i%prime[j]==0)
            {
                mu[i*prime[j]]=0;
                break;
            }
            mu[prime[j]*i]=-mu[i];
        }
    }
    for (int i=1; i<=n; i++)
    {
        sum[i]=sum[i-1]+mu[i];
    }
}
int ans(int n,int m)
{
    if (n>m)
    {
        swap(n,m);
    }
    int last,ret=0;
    for (int i=1; i<=n; i=last+1)
    {
        last=min(n/(n/i),m/(m/i));
        ret+=(n/i)*(m/i)*(sum[last]-sum[i-1]);
    }
    return ret;
}

int main()
{
    Mu(N);
    int _,a,b,c,d,k,ca=0;
    scanf("%d",&_);
    while (_--)
    {
        scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
        if (k==0)
        {
            printf("Case %d: 0\n",++ca);
            continue;
        }
        a--;
        c--;
        a/=k;
        b/=k;
        c/=k;
        d/=k;
        int Ans=ans(b,d)-ans(a,d)-ans(b,c)+ans(a,c);
        printf("%d\n",Ans);
    }
}

GCD

#include <bits/stdc++.h>

using namespace std;
const int N=200000;
typedef long long ll;
bool vis[N+10];
ll tot,prime[N+10],sum[N+10],mu[N+10];

void Mu(ll n)
{
    mu[1]=1;
    for (ll i=2; i<=n; i++)
    {
        if (!vis[i])
        {
            prime[++tot]=i;
            mu[i]=-1;
        }
        for (ll j=1; j<=tot&&prime[j]*i<=n; j++)
        {
            vis[prime[j]*i]=1;
            if (i%prime[j]==0)
            {
                mu[i*prime[j]]=0;
                break;
            }
            mu[prime[j]*i]=-mu[i];
        }
    }
    for (ll i=1; i<=n; i++)
    {
        sum[i]=sum[i-1]+mu[i];
    }
}
ll ans(ll n,ll m)
{
    if (n>m)
    {
        swap(n,m);
    }
    ll last,ret=0;
    for (ll i=1; i<=n; i=last+1)
    {
        last=min(n/(n/i),m/(m/i));
        ret+=(n/i)*(m/i)*(sum[last]-sum[i-1]);
    }
    return ret;
}

int main()
{
    Mu(N);
    int _,a,b,c,d,k,ca=0;
    scanf("%d",&_);
    while (_--)
    {
        scanf("%lld%lld%lld%lld%lld",&a,&b,&c,&d,&k);
        if (k==0)
        {
            printf("Case %d: 0\n",++ca);
            continue;
        }
        printf("Case %d: ",++ca);
        ll ans1=0,ans2=0;
        b/=k;
        d/=k;
        for (int i=1; i<=min(b,d); i++)
        {
            ans1+=mu[i]*(b/i)*(d/i);
        }
        for (int i=1; i<=min(b,d); i++)
        {
            ans2+=mu[i]*(min(b,d)/i)*(min(b,d)/i);
        }
        printf("%lld\n",ans1-ans2/2);
    }
}

YY的GCD

// luogu-judger-enable-o2
#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N=10000001;
bool vis[N+10];
ll tot,f[N+10];
int prime[N+10],mu[N+10];
inline ll read()
{
    ll res=0,f=1;
    char ch=getchar();
    while (!isdigit(ch))
    {
        if (ch=='-')
        {
            f=-f;
        }
        ch=getchar();
    }
    while (isdigit(ch))
    {
        res=(res<<3)+(res<<1)+ch-'0';
        ch=getchar();
    }
    return f*res;
}
void Mu(ll n)
{
    mu[1]=1;
    for (register ll i=2; i<=n; i++)
    {
        if (!vis[i])
        {
            prime[++tot]=i;
            mu[i]=-1;
        }
        for (register ll j=1; j<=tot&&prime[j]*i<=n; j++)
        {
            vis[prime[j]*i]=1;
            if (i%prime[j]==0)
            {
                mu[i*prime[j]]=0;
                break;
            }
            mu[prime[j]*i]=-mu[i];
        }
    }
    for (register ll i=1;i<=tot;i++){
        for (ll j=1;j*prime[i]<=n;j++){
            f[j*prime[i]]+=mu[j];
        }
    }
    for (register ll i=1;i<=n;i++){
        f[i]=f[i-1]+f[i];
    }
}
void print(ll x)
{
    if(x<0) putchar('-'),x=-x;
    if(x>9) print(x/10);
    putchar(x%10+'0');
}

int main(){
    ll _,m,n;
    Mu(N);
    _=read();
    while (_--){
        n=read();
        m=read();
        if (n>m){
            swap(n,m);
        }
        ll ans=0,r;
        for (register ll i=1;i<=n;i=r+1){
            r=min(n/(n/i),m/(m/i));
            ans+=(f[r]-f[i-1])*(n/i)*(m/i);
        }
        print(ans);
        putchar('\n');
    }
    return 0;
}

[POI2007]ZAP-Queries

#include <bits/stdc++.h>

using namespace std;
const int N=200000;
typedef long long ll;
bool vis[N+10];
ll tot,prime[N+10],sum[N+10],mu[N+10];

void Mu(ll n)
{
    mu[1]=1;
    for (ll i=2; i<=n; i++)
    {
        if (!vis[i])
        {
            prime[++tot]=i;
            mu[i]=-1;
        }
        for (ll j=1; j<=tot&&prime[j]*i<=n; j++)
        {
            vis[prime[j]*i]=1;
            if (i%prime[j]==0)
            {
                mu[i*prime[j]]=0;
                break;
            }
            mu[prime[j]*i]=-mu[i];
        }
    }
    for (ll i=1; i<=n; i++)
    {
        sum[i]=sum[i-1]+mu[i];
    }
}
int main()
{
    Mu(N);
    int _,ca=0;
    ll b,d,k;
    scanf("%d",&_);
    while (_--)
    {
        scanf("%lld%lld%lld",&b,&d,&k);
        ll ans1=0,ans2=0;
        b/=k;
        d/=k;
        if (b>d){
            swap(b,d);
        }
        ans1=0;
        int r;
        for (int i=1; i<=b;i=r+1)
        {
            r=min(b/(b/i),d/(d/i));
            ans1+=(b/i)*(d/i)*(sum[r]-sum[i-1]);
        }
        printf("%lld\n",ans1);
    }
}

  

 

posted @ 2019-08-16 09:33  Snow_in_winer  阅读(154)  评论(0编辑  收藏  举报