• UVA12558 埃及分数 数学知识 + 迭代加深 + dfs + 剪枝


    UVA12558 埃及分数

    题目链接

    ​ 数学知识 + 迭代加深 + dfs + 剪枝

    ​ 我觉得这道题还是比较难的,反正看题解看了好长时间。

    ​ 首先用迭代加深,枚举分解后的项数。

    ​ dfs时的上下界:下界为(lfloor frac{b}{a} floor + 1),上界是(a * i >= b * (maxdep - now + 1)),其中(i)为当前枚举的分母,(maxdep)为迭代加深枚举的项数,(dep)为当前枚举到了第几项。证明

    #include <bits/stdc++.h>
    
    #define int long long
    
    using namespace std;
    
    inline long long read() {
        long long s = 0, f = 1; char ch;
        while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
        for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
        return s * f; 
    }
    
    const int N = 1e5 + 5;
    int t, k, flag, maxdep;
    long long a, b;
    int w[N], tmp[N];
    set <int> q;
    
    int judge() {
        for(int i = maxdep;i >= 1; i--) 
            if(tmp[i] != w[i]) {
                if(tmp[i] > w[i] || tmp[i] == 0) return 0;
                else return 1;
            }
        return 1;
    }
    
    void copy() {
        for(int i = 1;i <= maxdep; i++) tmp[i] = w[i];
    }
    
    int gcd(int x, int y) {
        return y == 0 ? x : gcd(y, x % y);
    }
    
    void dfs(long long a, long long b, int now, long long last) {
        if(now == maxdep) {
            if(b % a || q.count(b / a)) return ;
            w[now] = b / a; 
            if(!judge()) copy();
            flag = 1; return ;
        }
        for(long long i = max(last, b / a + 1); ; i++) {
            if(q.count(i)) continue;
            if(i * a >= b * (maxdep - now + 1)) break;
            long long na = a * i - b, nb = b * i;
            long long g = gcd(na, nb);
            w[now] = i; dfs(na / g, nb / g, now + 1, i + 1);
        }
    }
    
    void Clear() {
        flag = 0; q.clear();
        memset(tmp, 0, sizeof(tmp));
    }
    
    signed main() {
    
        t = read();
        for(int l = 1;l <= t; l++) {
            Clear();
            a = read(); b = read(); k = read();
            for(int i = 1, x;i <= k; i++) x = read(), q.insert(x);
            for(maxdep = 2; ; maxdep++) {
                if(flag) break;
                memset(tmp, 0, sizeof(tmp));
                dfs(a, b, 1, b / a + 1);
            }
            printf("Case %lld: %lld/%lld=1/%lld", l, a, b, tmp[1]);
            for(int i = 2;i < maxdep; i++) printf("+1/%lld", tmp[i]);
            printf("
    ");
        }
    
        return 0;
    }
    
  • 相关阅读:
    协方差的意义
    ios7新特性实践
    微信支付大盗--黑色产业链
    UVA 297 Quadtrees(四叉树建树、合并与遍历)
    HDU 2876 Ellipse, again and again
    java中接口的定义与实现
    Oracle Linux 6.3下安装Oracle 11g R2(11.2.0.3)
    Fortran使用隐形DO循环和reshape给一维和多维数组赋初值
    Java实现 蓝桥杯VIP 算法训练 成绩的等级输出
    Java实现 蓝桥杯VIP 算法训练 成绩的等级输出
  • 原文地址:https://www.cnblogs.com/czhui666/p/13747821.html
Copyright © 2020-2023  润新知