bzoj2301-Problem b

题意

\(T\le 5\times 10^4\) 次询问,每次询问 \(a,b,c,d,k\le 5\times 10^4\),求
\[ \sum _{i=a}^b\sum _{j=c}^d[gcd(i,j)=k] \]

分析

重新学了一次(可能跟第一次学没什么区别)莫比乌斯反演相关,这题还是很简单的。问题可以转化为求四次
\[ \sum _{i=1}^n\sum _{j=1}^m[gcd(i,j)=1] \]
下面过程中设 \(n\le m\)
\[ \begin{aligned} \sum _{i=1}^n\sum _{j=1}^m[gcd(i,j)=k]&=\sum _{i=1}^n\sum _{j=1}^m\sum _{k|i,k|j}\sum _{d|\frac{i}{k},d|\frac{j}{k}}\mu(d) \\ &=\sum _{d=1}^n\sum _{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum _{j=1}^{\lfloor\frac{m}{k}\rfloor}\mu (d) \\ &=\sum _{d=1}^n\mu (d) \lfloor\frac{\lfloor\frac{n}{k}\rfloor}{d}\rfloor \lfloor\frac{\lfloor\frac{m}{k}\rfloor}{d}\rfloor \end{aligned} \]
注意到 \(\lfloor\frac{n}{d}\rfloor\) 这种形式只有 \(2\sqrt n\) 种取值(对于 \(d\le \sqrt n\) ,显然;对于 \(d>\sqrt n\)\(\lfloor\frac{n}{d}\rfloor\le \sqrt n\) ,也最多只有 \(\sqrt n\) 种),所以 \(\lfloor\frac{\lfloor\frac{n}{k}\rfloor}{d}\rfloor \lfloor\frac{\lfloor\frac{m}{k}\rfloor}{d}\rfloor\) 最多只有 \(4\sqrt n\) 种取值,跳一下即可做到单次询问 \(O(\sqrt n)\) ,只要预处理 \(\mu\) 函数的前缀和即可。

代码

#include<bits/stdc++.h>
using namespace std;
inline int read() {
    int x=0,f=1;
    char c=getchar_unlocked();
    for (;!isdigit(c);c=getchar_unlocked()) if (c=='-') f=-1;
    for (;isdigit(c);c=getchar_unlocked()) x=x*10+c-'0';
    return x*f;
}
typedef long long giant;
const int maxn=5e4+1;
bool np[maxn];
int p[maxn],mu[maxn],ps=0;
giant calc(int n,int m) {
    giant ret=0;
    if (n>m) swap(n,m);
    for (int i=1,j;i<=n;i=j+1) {
        j=min(n/(n/i),m/(m/i));
        ret+=(giant)(mu[j]-mu[i-1])*(n/i)*(m/i);
    }
    return ret;
}
int main() {
#ifndef ONLINE_JUDGE
    freopen("test.in","r",stdin);
#endif
    mu[1]=1;
    for (int i=2;i<maxn;++i) {
        if (!np[i]) p[++ps]=i,mu[i]=-1;
        for (int j=1;j<=ps && i*p[j]<maxn;++j) {
            np[i*p[j]]=true;
            if (i%p[j]==0) break;
            mu[i*p[j]]=-mu[i];
        }
    }
    for (int i=2;i<maxn;++i) mu[i]+=mu[i-1];
    int T=read();
    while (T--) {
        int a=read(),b=read(),c=read(),d=read(),k=read();
        a=(a-1)/k,b/=k,c=(c-1)/k,d/=k;
        giant ans=(calc(b,d)-calc(b,c))-(calc(a,d)-calc(a,c));
        printf("%lld\n",ans);
    }
    return 0;
}
posted @ 2017-08-09 15:45  permui  阅读(...)  评论(...编辑  收藏