zoukankan      html  css  js  c++  java
  • 「6月雅礼集训 2017 Day8」gcd

    【题目大意】

    定义times(a, b)表示用辗转相除计算a和b的最大公约数所需步骤。

    那么有:

    1. times(a, b) = times(b, a)

    2. times(a, 0) = 0

    3. times(a, b) = times(b, a mod b) + 1

    对于$1 leq x leq A, 1 leq y leq B$,求times(A, B)的最大值,以及有多少对数取到了最大值。

    多组数据。

    $T leq 3 imes 10^5, 1 leq A,B leq 10^{18}$

    【题解】

    我们打一个1000以内,times(x, y) = 13的表

    我们定义好数对为:$(x,y)$满足不存在$1 leq x' leq x, 1leq y'leq y$,使得times(x', y') > times(x, y)

    那么明显答案肯定是好数,我们发现,答案中的很多数都是由$(x,y)$经过$(x, x+ky)$变换来的。

    那么答案很多,但是$(x,y)$这样的数少,我们定义这样的数为极好数

    严格定义为$x leq fib_{x+2}, y leq fib_{x+2}$且times(x, y) = k的好数。

    我们可以发现并证明(显然),好数只要1步就能变成极好数

    那么我们只要求出极好数,就能推出好数的数量了。

    容易发现极好数很少,只要暴力求即可。

    比如当times = 13的时候,极好数的个数只有13.。。

    (就是把上面所有好数简化过后)

    那么我们就能暴力求啦

    发现times = x的极好数,是根据times = x-1的极好数(x, y)经过变换(y, x+ky)而来。那么我们只要根据极好数的定义求即可。

    复杂度$O(Qlog^2(A))$

    # include <vector>
    # include <stdio.h>
    # include <string.h>
    # include <iostream>
    # include <algorithm>
    
    using namespace std;
    
    typedef long long ll;
    typedef unsigned long long ull;
    typedef long double ld;
    
    const int N = 1e5 + 10, M = 2e5 + 10, F = 105;
    const int mod = 1e9 + 7;
    
    inline ll getll() {
        ll x = 0; char ch = getchar();
        while(!isdigit(ch)) ch = getchar();
        while(isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
        return x;
    }
    
    ll fib[F];
    
    struct pa {
        ll a, b;
        pa() {}
        pa(ll a, ll b) : a(a), b(b) {}
        friend bool operator == (pa a, pa b) {
            return a.a == b.a && a.b == b.b;
        }
        friend bool operator < (pa a, pa b) {
            return a.a < b.a || (a.a == b.a && a.b < b.b);
        }
        friend bool operator > (pa a, pa b) {
            return a.a > b.a || (a.a == b.a && a.b > b.b);
        }
    };
    
    vector<pa> g[M];
    
    int times = 0;
    inline int gcd(ll a, ll b) {
        if(a < b) swap(a, b);
        if(b == 0) return a;
        ++times;
        return gcd(b, a%b);
    }
    
    inline int calc(ll a, ll b) {
        times = 0;
        gcd(a, b);
        return times;
    }
    
    inline void gg(int x) {
        pa t; g[x].clear();
        for (int i=0; i<g[x-1].size(); ++i) {
            t = g[x-1][i];
            ll y = t.b; swap(t.a, t.b);
            for (t.b += y; t.b <= fib[x+2]; t.b += y) 
                if(calc(t.a, t.b) == x) g[x].push_back(t);
        }
        sort(g[x].begin(), g[x].end());
        g[x].erase(unique(g[x].begin(), g[x].end()), g[x].end());
    }
    
    ll A, B, ans, tem;
    inline void sol() {
        A = getll(), B = getll(); 
        if(A > B) swap(A, B);
        ans = 1; tem = 0;
        for (int i=2; i<90; ++i)
            if(fib[i] <= A && fib[i+1] <= B) ans = i;
            else break;    
        printf("%d ", ans);
        if(ans == 1) {
            printf("%d
    ", A % mod * (B % mod) % mod);
            return ;
        } else {
            for (int i=0; i<g[ans-1].size(); ++i) {
                ll a = g[ans-1][i].a, b = g[ans-1][i].b;
                if(b <= A) tem += (B-a)/b, tem %= mod;
                if(b <= B) tem += (A-a)/b, tem %= mod;
            }
        }
        printf("%lld
    ", tem);
    }
    
    int main() {
    //    freopen("gcd.in", "r", stdin);
    //    freopen("gcd.out", "w", stdout);
        fib[0] = 1, fib[1] = 1;
        for (int i=2; i<=90; ++i) fib[i] = fib[i-1] + fib[i-2];
        g[1].push_back(pa(1ll, 2ll)), g[1].push_back(pa(1ll, 3ll));
        for (int i=2; i<=88; ++i) gg(i);
        int T; cin >> T;
        while(T--) sol();
        return 0;
    }
    View Code

    upd: 加了个读入优化跑了rk2 

  • 相关阅读:
    LC.225. Implement Stack using Queues(using two queues)
    LC.232. Implement Queue using Stacks(use two stacks)
    sort numbers with two stacks(many duplicates)
    LC.154. Find Minimum in Rotated Sorted Array II
    LC.81. Search in Rotated Sorted Array II
    LC.35.Search Insert Position
    前后端分离:(一)
    Redis基本使用(一)
    GIT篇章(二)
    GIT篇章(一)
  • 原文地址:https://www.cnblogs.com/galaxies/p/20170624_c.html
Copyright © 2011-2022 走看看