BZOJ2671 Calc 【莫比乌斯反演】

题目链接

BZOJ2671

题解

\(d = (a,b)\)\(a = dx,b = dy\)
那么有
\[ \begin{aligned} d(x + y) | d^2xy \\ (x + y) | dxy \end{aligned} \]
由于\(x \perp y\),所以
\[(x + y) | d\]
\(d = k(x + y)\),那么较大的\(b = yk(x + 1)\)要满足\(b <= n\)
那么对于一组互质的\((x,y)\),合法的\(d\)的个数有
\[\lfloor \frac{n}{y(x + y)} \rfloor\]
那么就有式子
\[ \begin{aligned} ans &= \sum\limits_{x = 1}^{\sqrt{n}} \sum\limits_{y = x + 1}^{\sqrt{n}}[(x,y) = 1] \lfloor \frac{n}{y(x + y)} \rfloor \\ &= \sum\limits_{x = 1}^{\sqrt{n}} \sum\limits_{y = x + 1}^{\sqrt{n}}\lfloor \frac{n}{y(x + y)} \rfloor \sum\limits_{d | (x,y)} \mu(d) \\ &= \sum\limits_{d = 1}^{\sqrt{n}} \mu(d) \sum\limits_{x = 1}^{\lfloor \frac{n}{d} \rfloor} \sum\limits_{y = x + 1}^{\lfloor \frac{n}{d} \rfloor} \lfloor \frac{n}{y(x + y)} \rfloor\\ &= \sum\limits_{d = 1}^{\sqrt{n}} \mu(d) \sum\limits_{y = 1}^{\lfloor \frac{n}{d} \rfloor}\sum\limits_{x = 1}^{y - 1} \lfloor \frac{n}{y(x + y)} \rfloor\\ &= \sum\limits_{d = 1}^{\sqrt{n}} \mu(d) \sum\limits_{y = 1}^{\lfloor \frac{n}{d} \rfloor}\sum\limits_{x = y + 1}^{min(2y - 1,\lfloor \frac{n}{d} \rfloor)} \lfloor \frac{n}{d^2 yx} \rfloor \end{aligned} \]
里边可以整除分块,复杂度\(O(?n^{\frac{3}{4}})\)

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<map>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define cls(s,v) memset(s,v,sizeof(s))
#define mp(a,b) make_pair<int,int>(a,b)
#define cp pair<int,int>
using namespace std;
const int maxn = 100005,maxm = 100005,INF = 0x3f3f3f3f;
inline int read(){
    int out = 0,flag = 1; char c = getchar();
    while (c < 48 || c > 57){if (c == '-') flag = 0; c = getchar();}
    while (c >= 48 && c <= 57){out = (out << 1) + (out << 3) + c - 48; c = getchar();}
    return flag ? out : -out;
}
LL ans;
int n,m;
int p[maxn],isn[maxn],mu[maxn],pi,N = 100000;
void init(){
    mu[1] = 1;
    for (int i = 2; i <= N; i++){
        if (!isn[i]) p[++pi] = i,mu[i] = -1;
        for (int j = 1; j <= pi && i * p[j] <= N; j++){
            isn[i * p[j]] = true;
            if (i % p[j] == 0) break;
            mu[i * p[j]] = -mu[i];
        }
    }
}
LL cal(int n,int m){
    LL re = 0;
    for (int y = 1; y <= m; y++){
        int t = n / y;
        for (int x = y + 1,nxt; x < (y << 1) && x <= t; x = nxt + 1){
            nxt = min(t / (t / x),(y << 1) - 1);
            re += 1ll * (nxt - x + 1) * (t / x);
        }
    }
    return re;
}
int main(){
    n = read(); m = (int)sqrt(n);
    init();
    for (int d = 1; d <= m; d++) if (mu[d]) ans += mu[d] * cal(n / d / d,m / d);
    printf("%lld\n",ans);
    return 0;
}

转载于:https://www.cnblogs.com/Mychael/p/9286124.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值