您的位置:首页 > 其它

BZOJ2671 Calc 【莫比乌斯反演】

2018-07-09 21:35 387 查看

题目链接

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: