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;
    }
  • 相关阅读:
    poj 1860 Currency Exchange(最短路径的应用)
    poj 2965 The Pilots Brothers' refrigerator
    zoj 1827 the game of 31 (有限制的博弈论)
    poj 3295 Tautology (构造法)
    poj 1753 Flip Game(枚举)
    poj 2109 (贪心)
    poj 1328(贪心)
    Qt 对单个控件美化
    Qt 4基础
    Bash Shell
  • 原文地址:https://www.cnblogs.com/jungu/p/13540323.html
Copyright © 2011-2022 走看看