zoukankan      html  css  js  c++  java
  • 洛谷 P2522 [HAOI2011]Problem b

    题意:

    求$sum_{x=a}^{b}sum_{y=c}^{d}[gcd(x, y) = k]$

    思路:

       $ sum_{x=a}^{b}sum_{y=c}^{d}[gcd(x, y) = k]$

    $ = sum_{x=a}^{b}(sum_{y=1}^{d}[gcd(x, y) = k] - sum_{y=1}^{c-1}[gcd(x, y) = k])$

    $ = sum_{x=1}^{b}(sum_{y=1}^{d}[gcd(x, y) = k] - sum_{y=1}^{c-1}[gcd(x, y) = k]) - sum_{x=1}^{a - 1}(sum_{y=1}^{d}[gcd(x, y) = k] - sum_{y=1}^{c-1}[gcd(x, y) = k])$

    $ = sum_{x=1}^{b}sum_{y=1}^{d}[gcd(x, y) = k] - sum_{x=1}^{b}sum_{y=1}^{c-1}[gcd(x, y) = k] - sum_{x=1}^{a-1}sum_{y=1}^{d}[gcd(x, y) = k] + sum_{x=1}^{a-1}sum_{y=1}^{c-1}[gcd(x, y) = k]$

    令$sum(n, m) = sum_{x=1}^{n}sum_{y=1}^{m}[gcd(x, y) = k]$, 对$sum(n, m)$进行计算:

      $ sum_{x=1}^{n}sum_{y=1}^{m}[gcd(x, y) = k]$

    $= sum_{x=1}^{lfloorfrac{n}{k} floor}sum_{y=1}^{lfloorfrac{m}{k} floor}[gcd(x, y) = 1]$

    $ = sum_{x=1}^{lfloorfrac{n}{k} floor}sum_{y=1}^{lfloorfrac{m}{k} floor}varepsilon(gcd(i, j))$

    $ = sum_{x=1}^{lfloorfrac{n}{k} floor}sum_{y=1}^{lfloorfrac{m}{k} floor}sum_{i|gcd(x, y)} mu(i)$

    $ = sum_{i=1} mu(i) sum_{x=1}^{lfloorfrac{n}{k} floor}[i | x]sum_{y=1}^{lfloorfrac{m}{k} floor}[i | y]$

    $ = sum_{i=1} lfloorfrac{n}{ki} floor lfloorfrac{m}{ki} floor$

    即:$sum(n, m) = sum_{i=1} lfloorfrac{n}{ki} floor lfloorfrac{m}{ki} floor$

    代入原式:$ans = sum(b, d) - sum(b, c - 1) - sum(a - 1, d) + sum(a - 1, c - 1)$即为答案

    Code:

    #pragma GCC optimize(3)
    #pragma GCC optimize(2)
    #include <map>
    #include <set>
    // #include <array>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <sstream>
    #include <iostream>
    #include <stdlib.h>
    #include <algorithm>
    // #include <unordered_map>
    
    using namespace std;
    
    typedef long long ll;
    typedef pair<int, int> PII;
    
    #define Time (double)clock() / CLOCKS_PER_SEC
    
    #define sd(a) scanf("%d", &a)
    #define sdd(a, b) scanf("%d%d", &a, &b)
    #define slld(a) scanf("%lld", &a)
    #define slldd(a, b) scanf("%lld%lld", &a, &b)
    
    const int N = 1e7 + 20;
    const int M = 1e5 + 20;
    const int mod = 1e9 + 7;
    const double eps = 1e-6;
    
    ll cnt = 0, primes[N], phi[N], mu[N], sum[N] = {0};
    map<ll, ll> su;
    bool st[N];
    
    int n, m, p, k;
    
    void get(ll n){
        // phi[1] = 1;
        mu[1] = 1;
        for(ll i = 2; i <= n; i ++){
            if(!st[i]){
                primes[cnt ++] = i;
                // phi[i] = i - 1;
                mu[i] = -1;
            }
            for(int j = 0; primes[j] <= n / i; j ++){
                st[i * primes[j]] = true;
                if(i % primes[j] == 0){
                    // phi[i * primes[j]] = primes[j] * phi[i];
                    mu[i * primes[j]] = 0;
                    break;
                }
                // phi[i * primes[j]] = (primes[j] - 1) * phi[i];
                mu[i * primes[j]] = - mu[i];
            }
        }
    
        for(int i = 1; i <= n; i ++){
            sum[i] = sum[i - 1] + mu[i];
        }
    }
    
    int get_sum(int n){
        if(n <= k) return sum[n];
        if(su[n]) return su[n];
    
        ll res = 1;
        for(int i = 2, r; i <= n; i = r + 1){
            r = n / (n / i);
            res -= (r - i + 1) * get_sum(n / i);
        }
        return su[n] = res;
    }
    
    int cal(int a, int b){
        int res = 0, mid1, mid2 = 0;
        if(a > b) swap(a, b);
        for(int i = 1, r; i <= a; i = r + 1){
            r = min(a / (a / i), b / (b / i));
            mid1 = get_sum(r);
            res = res + (mid1 - mid2) * (a / i) * (b / i);
            mid2 = mid1;
        }
        return res;
    }
    
    void solve()
    {
        int a, b, c, d, kk;
        sdd(a, b);
        sdd(c, d);
        sd(kk);
    
        a --, c --;
    
        a /= kk, b /= kk, c /= kk, d /= kk;
        int ans = cal(b, d) - cal(b, c) - cal(a, d) + cal(a, c);
        cout << ans << endl;
    }
    
    int main()
    {
    #ifdef ONLINE_JUDGE
    #else
        freopen("/home/jungu/code/in.txt", "r", stdin);
        // freopen("/home/jungu/code/out.txt", "w", stdout);
        // freopen("/home/jungu/code/practice/out.txt","w",stdout);
    #endif
        // ios::sync_with_stdio(false);
        cin.tie(0), cout.tie(0);
    
        int T = 1;
        sd(T);
        k = (int)pow(50000, 0.666667);
        get(k);
        // init(10000000);
        // int cas = 1;
        while (T--)
        {
            // printf("Case #%d:", cas++);
            solve();
        }
    
        return 0;
    }
  • 相关阅读:
    K2路由器刷机教程
    GitBook Editor使用教程
    source tree使用教程
    github与github网站push神器
    tgp助手开启逆战游戏无反应
    如何计算服务器指标参数
    排序--堆排序算法
    排序--希尔排序算法
    排序--直接插入排序算法
    排序--冒泡排序算法
  • 原文地址:https://www.cnblogs.com/jungu/p/13540323.html
Copyright © 2011-2022 走看看