#include<set>#include<queue>#include<cstdio>#include<vector>#include<string>#include<cstring>#include<iostream>#include<algorithm>#define ll long longusingnamespace std;
int T, now, ans, x;
int n, l, r, k, a[101];
intmain(){
scanf("%d", &T);
while (T--) {
scanf("%d %d %d %d", &n, &l, &r, &k);
a[0] = 0; now = 0; ans = 0;
for (int i = 1; i <= n; i++) {
scanf("%d", &x);
if (l <= x && x <= r) a[++a[0]] = x;
}
sort(a + 1, a + a[0] + 1);
for (int i = 1; i <= a[0]; i++) {
now += a[i]; ans++;
if (now > k) {
now -= a[i]; ans--;
break;
}
}
printf("%d\n", ans);
}
return0;
}
B:Divan and a New Project
题目大意
给你一个直线,然后起点在 0 位置,然后有 n 个地方可以让你选放在这个直线的 n 个地方(1~n 位置),然后每个地方要有去的次数。
每次去这个地方的费用是 2|x0−xi|(就是两个地方的距离差乘二),然后要你最小化费用并给出放置方案。
思路
显然又是一个贪心,就尽可能的把要去次数多的放的靠近 0 位置即可。
(也是一个排序的事情)
代码
#include<set>#include<queue>#include<cstdio>#include<vector>#include<string>#include<cstring>#include<iostream>#include<algorithm>#define ll long longusingnamespace std;
structnode {
int x, id;
}a[200001];
int T;
int n, ans[200001];
ll answ, bas;
boolcmp(node x, node y){
return x.x < y.x;
}
intmain(){
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &a[i].x), a[i].id = i;
sort(a + 1, a + n + 1, cmp);
answ = 0; bas = 1;
bool op = 0;
ans[0] = 0;
for (int i = n; i >= 1; i--) {
ans[a[i].id] = bas;
if (op) ans[a[i].id] = -bas;
answ += 2ll * a[i].x * bas;
if (op == 0) op = 1;
else {
bas++; op = 0;
}
}
printf("%lld\n", answ);
for (int i = 0; i <= n; i++)
printf("%d ", ans[i]);
printf("\n");
}
return0;
}
C:Divan and bitwise operations
题目大意
要你构造一个长为为 n 的数组,然后有一些限制条件:某一段区间的数与起来的结果是某个数。
然后要你输出你构造出的数组的权值,定义这个权值是它所有子序列的异或和的和。
然后多种构造方法输出任意一个的答案即可。
首先你算当前能有的所有数都用 x 来贡献。
(那我们也就是要处理出每个数有多少个数是它的倍数,这个不难处理,每个数用质数遍历因子加即可)
那你就枚举下一次变成的倍数。
那如果当前有的数是 nx,当前枚举到的倍数是 y,这个 y 有 ny 个数是它的倍数。
那我们首先要减去这 ny 个 x 个贡献,再加上 dfs(y) 的结果,我们要最大化这个部分。
然后就可以了。
代码
#include<set>#include<queue>#include<cstdio>#include<vector>#include<string>#include<cstring>#include<iostream>#include<algorithm>#define ll long longusingnamespace std;
int n, a[100001];
int pl[5000001];
int np[5000001], prime[5000001];
int cnt[10001], cntpl[10001];
ll num[5000001], rem[5000001];
voidyz(int now, int va, int xx){
if (now > cntpl[0]) {
num[va] += xx; return ;
}
yz(now + 1, va, xx);
for (int i = 1; i <= cnt[now]; i++) {
va *= cntpl[now];
yz(now + 1, va, xx);
}
}
ll dfs(int now){
if (rem[now]) return rem[now];
ll re = 0;
for (int i = now + now; i <= 5000000; i += now) {
if (!num[i]) continue;
re = max(re, dfs(i) - num[i] * now);
}
return rem[now] = (re + num[now] * now);
}
intmain(){
for (int i = 2; i <= 5000000; i++) {
if (!np[i]) {
prime[++prime[0]] = i;
pl[i] = prime[0];
}
for (int j = 1; j <= prime[0] && i * prime[j] <= 5000000; j++) {
np[i * prime[j]] = prime[j];
if (i % prime[j] == 0) break;
}
}
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
sort(a + 1, a + n + 1);
for (int l = 1; l <= n; l++) {
int r = l;
while (r < n && a[r + 1] == a[l]) r++;
int noww = a[l];
cntpl[0] = 0;
while (noww) {
if (noww == 1) break;
cnt[++cntpl[0]] = 0;
cntpl[cntpl[0]] = (np[noww] ? np[noww] : noww);
while (noww % cntpl[cntpl[0]] == 0) {
noww /= cntpl[cntpl[0]];
cnt[cntpl[0]]++;
}
}
yz(1, 1, r - l + 1);
l = r;
}
printf("%lld\n", dfs(1));
return0;
}
D2:Divan and Kostomuksha (hard version)
题目大意
同 D1,但是每个数的大小更大,不能用 O(VlogV) 的复杂度解决。(V 是数的最大值)
思路
考虑会超时的部分,发现是你 dfs 里面枚举倍数不行,别的地方都可以。
考虑改进。
会发现你乘一个 z 的倍数,如果 z=x∗y,你完全可以先走到 x 倍,再走到 x∗y 倍。
那你就只需要枚举它乘上每个质数,就可以了。
复杂度就降到了 O(VloglogV)。
代码
#include<set>#include<queue>#include<cstdio>#include<vector>#include<string>#include<cstring>#include<iostream>#include<algorithm>#define ll long longusingnamespace std;
int n, a[100001];
int pl[20000001];
int np[20000001], prime[20000001];
int cnt[100001], cntpl[100001];
ll num[20000001], rem[20000001];
voidyz(int now, int va, int xx){
if (now > cntpl[0]) {
num[va] += xx; return ;
}
yz(now + 1, va, xx);
for (int i = 1; i <= cnt[now]; i++) {
va *= cntpl[now];
yz(now + 1, va, xx);
}
}
ll dfs(int now){
if (rem[now]) return rem[now];
ll re = 0;
for (int i = 1; i <= prime[0] && 1ll * now * prime[i] <= 20000000; i++) {
if (!num[now * prime[i]]) continue;
re = max(re, dfs(now * prime[i]) - num[now * prime[i]] * now);
}
return rem[now] = (re + num[now] * now);
}
intmain(){
for (int i = 2; i <= 20000000; i++) {
if (!np[i]) {
prime[++prime[0]] = i;
pl[i] = prime[0];
}
for (int j = 1; j <= prime[0] && i * prime[j] <= 20000000; j++) {
np[i * prime[j]] = prime[j];
if (i % prime[j] == 0) break;
}
}
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
sort(a + 1, a + n + 1);
for (int l = 1; l <= n; l++) {
int r = l;
while (r < n && a[r + 1] == a[l]) r++;
int noww = a[l];
cntpl[0] = 0;
while (noww) {
if (noww == 1) break;
cnt[++cntpl[0]] = 0;
cntpl[cntpl[0]] = (np[noww] ? np[noww] : noww);
while (noww % cntpl[cntpl[0]] == 0) {
noww /= cntpl[cntpl[0]];
cnt[cntpl[0]]++;
}
}
yz(1, 1, r - l + 1);
l = r;
}
printf("%lld\n", dfs(1));
return0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现