2015 ACM ICPC Singapore Regional D(折半枚举+二分)
D - Association of Computer Maintenance
题意
给定至多350个小于100的质数,对于所有质数之积k将它分解为两个数a和b使得a*b=k。输出最小的a+b,并对1e9+7取模
分析
首先考虑想如果想让a+b最小,即让abs(a-b)最小。根据限制条件k的因子数不超过1e10,容易想到将k拆分成k1和k2,此时对于k1和k2的因子数都不超过1e5。考虑将k1的所有因子存下,最后再枚举k2的所有因子去匹配最接近的k1因子,记录下最小值即可。
注意维护因子时由于高精度过慢,考虑转换成对数比较大小。时间复杂O(nlogn)。
代码实现
#include <bits/stdc++.h>
int main() {
std::cin.tie(nullptr)->sync_with_stdio(false);
#define int long long
constexpr int P = 1e9 + 7;
std::string str;
std::cin >> str;
std::vector<int> pri;
for (int i = 0; i < (int)size(str); i += 2) {
pri.emplace_back((str[i] - '0') * 10 + (str[i + 1] - '0'));
}
std::sort(pri.begin(), pri.end());
std::vector<std::pair<int, int>> fac;
for (int i = 0; i < (int)size(pri); ++i) {
int j = i + 1;
while (j < (int)size(pri) && pri[i] == pri[j]) j += 1;
fac.emplace_back(pri[i], j - i);
i = j - 1;
}
int pos = (int)size(fac) - 1;
for (int i = 0, j = 1; i < (int)size(fac); ++i) {
if (j * (fac[i].second + 1) > 4e5) {
pos = i - 1;
break;
} else {
j *= fac[i].second + 1;
}
}
auto power = [&](int a, int b) {
int c = 1;
for (; b; b >>= 1, a = a * a % P)
if (b & 1) c = c * a % P;
return c;
};
std::vector<std::pair<int, int>> s;
std::vector<std::pair<double, int>> prod;
int idx = 0;
auto dfs = [&](auto &&self, int u, double diff, int s1, int s2) ->void {
if (u == pos + 1) {
prod.emplace_back(diff, idx++);
s.emplace_back(s1, s2);
return ;
}
auto [p, cnt] = fac[u];
for (int i = 0; i <= cnt; ++i) {
self(self, u + 1, diff + log(p) * (i + i - cnt), s1 * power(p, i) % P, s2 * power(p, cnt - i) % P);
}
};
dfs(dfs, 0, 0, 1, 1);
std::sort(prod.begin(), prod.end());
int ans = 0;
double max = 1e100;
auto find = [&](auto &&self, int u, double diff, int s1, int s2) ->void {
if (u == (int)size(fac)) {
int p = std::lower_bound(prod.begin(), prod.end(), std::pair<double, int>{-diff, -1}) - prod.begin();
if (p < (int)size(prod)) {
auto [w, id] = prod[p];
if (fabs(diff + w) < max) {
max = fabs(diff + w);
ans = ( s1 * s[id].first % P + s2 * s[id].second % P) % P;
}
}
if (p - 1 >= 0) {
auto [w, id] = prod[p - 1];
if (fabs(diff + w) < max) {
max = fabs(diff + w);
ans = ( s1 * s[id].first % P + s2 * s[id].second % P) % P;
}
}
return ;
}
auto [p, cnt] = fac[u];
for (int i = 0; i <= cnt; ++i) {
self(self, u + 1, diff + log(p) * (i + i - cnt), s1 * power(p, i) % P, s2 * power(p, cnt - i) % P);
}
};
find(find, pos + 1, 0, 1, 1);
std::cout << ans << '\n';
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理