B. A Balanced Problemset

原题链接

忠告1:要学会计算时间复杂度!!

忠告2:要学会抓事实,不要掉进题目直观模拟的陷阱里

事实

1.任意k个数的 \(gcd\) 一定可以是这k个数的最小值,这里以 \(k=3\) 举例
假设 \(gcd(a_1,a_2,a_3)=m\) ,则 \(a_1=k_1m,a_2=k_2m,a_3=k_3m\),其中 \(k_1,k_2,k_3\) 都是整数
那么可以通过移项变成 \(a_1=(k_1+k_3-1)m,a_2=k_2m,a_3=m\)
2.将n分成k个数的和,这k个数中的最小值 \(a_{min} \le \frac{n}{k}\) 对任何n,k都成立
很显然啊,拿 \(k=2\) 的情况举个例子就很明显了,\(k\) 推广开来也是一样的
3.根据事实12,当 \(a_{min}\)\(n\) 的因子时,答案就是 \(a_{min}\)
于是我们可以 \(put\ it\ into\ simple\ words:\) ,找出 \(n\) 的小于 \(\frac{n}{k}\) 的 最大因子

判断时间复杂度

最坏情况: \(t=10^3,n=10^8,k=1\) , $10^{11} > 10^8 $
直接从 \(\frac{n}{k}\) 开始往下遍历很大概率T
我们考虑优化
由于答案一定是 \(n\) 的因子,而因子成对出现(包括1和自身),所以我们开根号找因子,每找一个因子相当于找到两个因子,对每个因子进行判断是否小于 \(\frac{n}{k}\)
此时 最坏情况 \(10^7\)

\(Code\)

#include<bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false); 
    cin.tie(NULL);
    int t;
    cin >> t;
    while(t--) {
        int n, k;
        cin >> n >> k;
        int result = 1; 
        for(int i = 1; i <= sqrt(n); i++) {
            if(n % i == 0) {
                if(i <= n / k) result = max(result, i);
                if(n / i <= n / k) result = max(result, n / i);
            }
        }
        cout << result << endl;
    }
    return 0;
}

posted @ 2024-01-28 17:25  纯粹的  阅读(248)  评论(0)    收藏  举报