【BZOJ2301】【HAOI2011】Problem B

题面

https://www.luogu.org/problem/P2522

题解

$Möbius\ inversion$的第一题,作为新的开始。

话说我们通常使用的式子是$$g(x)=\sum_{x|d}{f(d)} \Leftrightarrow f(x)=\sum_{i \ge 1}{\mu(i) g(i)}$$.

是一个相当明科但是很好理解的式子(卷积变点乘)我晕了,这么重要的式子竟然在《具体数学》上没有提到。。。

#include<cstdio>
#include<cstring>
#include<iostream>
#define ri register int
#define N 50500
#define LL long long
using namespace std;

inline int read() {
    int ret=0,f=0; char ch=getchar();
    while (ch<'0' || ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0' && ch<='9') ret=(ret<<1)+(ret<<3)+(ch^48),ch=getchar();
    return f?-ret:ret;
}

int mu[N],cnt,f[N];
int prime[N];

void getmu() {
    mu[1]=1;
    for (ri i=2;i<N;i++) {
        if (!f[i]) {
            prime[++cnt]=i;
            mu[i]=-1;
        }
        for (ri j=1;i*prime[j]<N;j++) {
            f[i*prime[j]]=1;
            if (i%prime[j]) {
                mu[i*prime[j]]=-mu[i];
            }
            else {
                mu[i*prime[j]]=0;
                break;
            }
        }
    }
    for (ri i=1;i<N;i++) mu[i]+=mu[i-1];
}

LL calc(int k,int n,int m) {
    n/=k; m/=k;
    LL ret=0;
    for (ri i=1,j;i<=min(n,m);i=j+1) {
        j=min(n/(n/i),m/(m/i));
        ret+=(mu[j]-mu[i-1])*1LL*(n/i)*1LL*(m/i);
    }
    return ret;
}

int main() {
    getmu();
    int T=read();
    while (T--) {
        int a=read(),b=read(),c=read(),d=read(),k=read();
        cout<<calc(k,b,d)-calc(k,a-1,d)-calc(k,b,c-1)+calc(k,a-1,c-1)<<endl;
    }
    return 0;
}

 

posted @ 2019-11-22 17:47  HellPix  阅读(172)  评论(0编辑  收藏  举报