zoukankan      html  css  js  c++  java
  • F. Equal Product (数学,思维,暴力)

    题目:传送门

    题意

    给你 n,m,l,r;你需要找到 (x1, x2, y1, y2) 这样的四元组,满足:

    1 <= x1 < x2 <= n;

    1 <= y2 < y1 <= m;

    x1*y1 = x2*y2;

    l <= x1*y1 <= r;

    对于每个x1=1,2,....n; 输出任意一个满足条件的四元组,若不存在这样的四元组,输出 -1;

    1<=n,m<=2e5; 1 <= l <= r <= n * m;

    思路

    对于 x1*y1 = x2*y2; 我们假设  x1 < x2,可以证明总是存在一对(a,b) (a | x1, b | y1, a < b) 使得 x2 = x1 / a * b; y2 = y1 / b * a;

    我可以枚举 x1,然后知道了 x1 就确定了 y1 的取值范围,由于 a 是 x1 的因子,我们可以枚举 a,通过 a 去 确定 b,若 b 确定了,则所有数都确定了。

    我们可以在 o(nlogn) 的时间内算出所有的 (x1, a); 

    然后我们枚举 x1,通过 x1 可以确定 y1 的取值范围,是一段区间,并且随着 x1 的增大,这个区间一直在收缩;对于这个区间的维护,我们可以用两个指针,指向这段区间的左端和右端;然后随着 x1 的变化,动态的维护这段区间即可。

    我们可以用 set 存 y1 的所有所有可能取值的所有因子,这样, set里面存的数就是 b 的可能取值。

    对于每个 a,若 x1 / a * b <= n;则存在答案;所以,若第一个大于a的b满足 x1 / a * b <= n;就更新 x1 的答案;

    我们可以通过 upper_bound 找到 set 中第一个大于 a 的 b;

    #include <bits/stdc++.h>
    #define LL long long
    #define rep(i, j, k) for(int i = j; i <= k; i++)
    #define dep(i, j, k) for(int i = k;i >= j; i--)
    #define pb push_back
    #define make make_pair
    #define fir first
    #define sec second
    using namespace std;
    
    const int N = 1e6 + 5;
    
    LL n, m;
    
    LL l, r;
    
    vector < LL > Y[N];
    
    pair < LL, LL > ans1[N], ans2[N];
    
    set < LL > Q;
    
    vector < LL > id(N, 0);
    
    vector < LL > cnt(N, 0);
    
    void solve() {
    
        scanf("%lld %lld %lld %lld", &n, &m, &l, &r);
    
        rep(i, 1, 200000) { /// 枚举所有 (x1, a)
    
            for(LL j = i; j <= 200000; j += i) {
    
                Y[j].pb(i);
    
            }
    
        }
    
        LL nowl = m + 1; /// y1的可能取值区间的左端点;
    
        LL nowr = m; /// y1 的可能取值区间的右端点
    
        rep(x1, 1, n) { /// 枚举 x1
    
            LL LY = (l + x1 - 1) / x1; /// 确定当前的 y1 可能取值区间的左端点;
    
            LL RY = r / x1; /// 确定当期 y1 的可能取值区间的右端点
    
            while(nowl > LY) { /// 移动左指针,维护 y1 的可能取值区间
    
                nowl--;
    
                for(int v : Y[nowl]) {
    
                    if(cnt[v] == 0) Q.insert(v);
    
                    cnt[v]++;
    
                    id[v] = nowl;
    
                }
    
            }
    
            while(nowr > RY) { /// 移动右指针
    
                for(int v : Y[nowr]) {
    
                    cnt[v]--;
    
                    if(cnt[v] == 0) Q.erase(v);
    
                }
    
                nowr--;
    
            }
    
            for(auto a : Y[x1]) { /// 枚举 a
    
                auto v = Q.upper_bound(a);
    
                if(v == Q.end()) continue;
    
                int b = *v;
    
                if(x1 / a * b <= n) { /// 满足条件,更新答案
    
                    int y1 = id[b];
    
                    ans1[x1] = make(x1, y1);
    
                    ans2[x1] = make(x1 / a * b, y1 / b * a);
    
                }
    
            }
    
        }
    
        rep(i, 1, n) {
    
            if(ans1[i].fir != 0) {
    
                printf("%lld %lld %lld %lld
    ", ans1[i].fir, ans1[i].sec, ans2[i].fir, ans2[i].sec);
    
            }
    
            else puts("-1");
    
        }
    
    }
    
    int main() {
    
    //    int _; scanf("%d", &_);
    //    while(_--) solve();
    
        solve();
    
        return 0;
    
    }
  • 相关阅读:
    大二暑假学习第一周
    PyQt5+pycharm 中对生成的.py文件无法运行的问题
    尚筹网19总结
    尚筹网19项目部署
    MAC远程连接Linux
    尚筹网17订单、支付
    尚筹网16确认回报、订单
    支付宝沙箱环境
    内网穿透
    支付宝开发平台使用
  • 原文地址:https://www.cnblogs.com/Willems/p/13696299.html
Copyright © 2011-2022 走看看