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

模板 - 莫比乌斯反演

时间:2019-04-18 01:02:00      阅读:195      评论:0      收藏:0      [点我收藏+]

标签:fine   www   最简   top   for   show   开始   class   ace   

P3455 [POI2007]ZAP-Queries https://www.luogu.org/problemnew/show/P3455

最简单的求gcd==d的个数,直接分块瞎搞。

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

#define MAXN 50000
int mu[MAXN+5];

int pri[MAXN+5],pritop;
bool notpri[MAXN+5];
//pritop从1开始计数

int summu[MAXN+5];

void sieve3(int n) {
    notpri[1]=mu[1]=1;
    for(int i=2; i<=n; i++) {
        if(!notpri[i])
            pri[++pritop]=i,mu[i]=-1;
        for(int j=1; j<=pritop&&i*pri[j]<=n; j++) {
            notpri[i*pri[j]]=1;
            //略有不同
            if(i%pri[j])
                mu[i*pri[j]]=-mu[i];
            else {
                mu[i*pri[j]]=0;
                break;
            }
        }
    }

    for(int i=1;i<=n;i++){
        summu[i]=summu[i-1]+mu[i];
    }
}

//整除分块,n,m版
ll aliquot_patition(ll n,ll m,ll d) {
    ll ans=0;
    int N=min(n,m);
    for(ll l=1,r; l<=N; l=r+1) {
        r=min(n/(n/l),m/(m/l));
        ans+=1ll*(n/(l*d))*(m/(l*d))*(summu[r]-summu[l-1]);
    }
    return ans;
}

int main() {
    sieve3(MAXN);
    int t;
    scanf("%d",&t);
    int n,m,d;
    while(~scanf("%d%d%d",&n,&m,&d)){
        printf("%lld\n",aliquot_patition(n,m,d));
    }
}

https://www.luogu.org/problemnew/show/P2522

没事别用 long long ,常数卡死你!

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

#define MAXN 50000
int mu[MAXN+5];

int pri[MAXN+5],pritop;
bool notpri[MAXN+5];
//pritop从1开始计数

int summu[MAXN+5];

void sieve3(int n) {
    notpri[1]=mu[1]=1;
    for(int i=2; i<=n; i++) {
        if(!notpri[i])
            pri[++pritop]=i,mu[i]=-1;
        for(int j=1; j<=pritop&&i*pri[j]<=n; j++) {
            notpri[i*pri[j]]=1;
            //略有不同
            if(i%pri[j])
                mu[i*pri[j]]=-mu[i];
            else {
                mu[i*pri[j]]=0;
                break;
            }
        }
    }

    for(int i=1;i<=n;i++){
        summu[i]=summu[i-1]+mu[i];
    }
}

//整除分块,n,m版
int aliquot_patition(int n,int m,int d) {
    int ans=0;
    int N=min(n,m);
    for(int l=1,r; l<=N; l=r+1) {
        r=min(n/(n/l),m/(m/l));
        ans+=1ll*(n/(l*d))*(m/(l*d))*(summu[r]-summu[l-1]);
    }
    return ans;
}

int solve(int a,int b,int c,int d,int k){
    int sum1=aliquot_patition(b,d,k);
    int sum2=aliquot_patition(a-1,d,k);
    int sum3=aliquot_patition(b,c-1,k);
    int sum4=aliquot_patition(a-1,c-1,k);
    return sum1+sum4-sum2-sum3;
}

int main() {
    sieve3(MAXN);
    int t;
    scanf("%d",&t);
    int a,b,c,d,k;
    while(~scanf("%d%d%d%d%d",&a,&b,&c,&d,&k)){
        printf("%d\n",solve(a,b,c,d,k));
    }
}

模板 - 莫比乌斯反演

标签:fine   www   最简   top   for   show   开始   class   ace   

原文地址:https://www.cnblogs.com/Yinku/p/10727114.html

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