zoukankan      html  css  js  c++  java
  • loj6482. LJJ 爱数数

    题意

    给出(n leq {10} ^ {12}),求

    [sum_{a = 1} ^ n sum_{b = 1} ^ n sum_{c = 1} ^ n [frac{1}{a} + frac{1}{b} = frac{1}{c}] [gcd(a, b, c) = 1] ]

    题解

    [egin{aligned} = & sum_{a = 1} ^ n sum_{b = 1} ^ n sum_{c = 1} ^ n [c(a + b) = ab] [(a, b, c) = 1] \ = & sum_{a = 1} ^ n sum_{b = 1} ^ n [(a + b) | ab] [(a, b, frac{ab}{a + b}) = 1] \ end{aligned} ]

    (g = (a, b)),则一对((a, b))合法的充要条件(a + b = g ^ 2)
    则原问题相当于求

    [egin{aligned} sum_{g = 1} ^ {sqrt {2n}} sum_i [(g ^ 2 - i g, i g) = g] = & sum_{g = 1} ^ {sqrt {2n}} sum_i [(g, i) = 1] \ end{aligned} ]

    考虑(i)的上下界

    [1 leq i g leq n \ 1 leq g ^ 2 - i g leq n \ ]

    [i in  cap left[ max(g - lfloor frac{n}{g} floor,1), min(lfloor frac{n}{g} floor, g - 1) ight] ]

    即求

    [sum_{g = 1} ^ {sqrt{2n}} sum_{i = ext{lowerbound}} ^ { ext{upperbound}} [(g, i) = 1] ]

    考虑对后面的东西做前缀和是

    [f(L) = sum_{i = 1} ^ L [(g, i) = 1] ]

    反演一下可以得到

    [f(L) = sum_{d | g} mu(d) lfloor frac{L}{d} floor ]

    则原式即求

    [sum_{g = 1} ^ {sqrt {2n}} f( ext{upperbound}) - f( ext{lowerbound} - 1) ]

    复杂度(mathcal O(sqrt n log n))

    #include <bits/stdc++.h>
    typedef long long ll;
    using namespace std;
    const int N = 2e6 + 5, M = 4e7 + 5;
    ll n, m, ans;
    int p[N], mu[N], vis[N], d[M], tmp[N], cnt[N];
    int calc (int g, int n) {
    	int ret = 0;
    	for (int i = cnt[g - 1] + 1; i <= cnt[g]; ++i) {
    		ret += mu[d[i]] * (n / d[i]);
    	}
        return ret;
    }
    int main () {
    	cin >> n, mu[1] = 1;
    	for (int i = 2; i < N; ++i) {
    		if (!vis[i]) {
    			p[++p[0]] = i, mu[i] = -1;
    		}
    		for (int j = 1; j <= p[0] && i * p[j] < N; ++j) {
    			vis[i * p[j]] = 1;
    			if (i % p[j] == 0) {
    				mu[i * p[j]] = 0;
    				break;
    			}
    			mu[i * p[j]] = -mu[i];
    		}
    	}
    	m = sqrt(n * 2);
    	for (int i = 1; i <= m; ++i) {
    		if (mu[i]) {
    			for (int j = i; j <= m; j += i) {
    				++cnt[j];
    			}
    		}
    		cnt[i] += cnt[i - 1];
    	}
    	for (int i = 1; i <= m; ++i) {
    		if (mu[i]) {
    			for (int j = i; j <= m; j += i) {
    				d[cnt[j - 1] + (++tmp[j])] = i;
    			}
    		}
    	}
    	for (int g = 1; g <= m; ++g) {
    		ans += calc(g, min(n / g, 0ll + g - 1)) - calc(g, max(0ll + g - n / g, 1ll) - 1);
    	}
    	cout << ans << endl;
    	return 0;
    }
    
  • 相关阅读:
    [Java]用递归判断是否为递减数组
    android欢迎界面的编程实现[手相评分软件实例]
    工作两周年的感想
    最新基于adtbundlewindowsx86的android开发环境搭建
    新浪微博Failed to receive access token
    朋友
    房产中介
    房产中介
    与 Josh Bloch 探讨 Java 未来
    关于英语学习的一点思考
  • 原文地址:https://www.cnblogs.com/psimonw/p/11674016.html
Copyright © 2011-2022 走看看