2025-01-09日记
反正你也写不出来题,不如来写日记。
上午
有日记的那天一定有考试。
T1
赛时想法:
T2
赛时做法:先考虑熊熊的方案。很简单,就是先把 按照和排序,然后依次把 的记录进答案。如果有那种 的,可以把它放在两边,那样也能够有贡献。
再考虑梦梦的方案。梦梦肯定要尽可能的吧和最小的那对 塞进熊熊的区间内。但是他先手,他不知道熊熊如何取,为了尽可能的碰到熊熊的区间,他肯定吧他放在数组的中间,以最大化碰到熊熊区间的可能性。
T3
德塔斯抓克车儿啊,写不了一点。
T4
因为死磕 T2 去了,所以没写。但是似乎有点思路?
看到第一句话,你应该想到这是在考试里写的日记,个人感觉今天要爆零。上面说了 T4 有思路,但是也仅限有思路,因为好歹还是一道 T4 是吧,最后 min 怎么可能写的完呢?
中午
颓废了一中午。
其实也不是颓废啦,就是无所事事而已。
感觉有点浪费时间,但是内耗更浪费时间,所以还是算了,别想了
下午
改题。
T1
直到现在都云里雾里的。
T2
一道 dp,码量奇大无比。
以下为 自己骂自己:
你 tm 连蓝色的 dp 都 tmd 写的出来,被 tmd 这么一道小的 dp 创翻了?你 tm 有没有点出息?
你说的对,但是我能做到蓝色紫色 dp 仅限于数位 dp 和板一点的斜率优化 dp。偶尔也能做线性 dp。
但是你 tm 不是切过一道蓝色的线性 dp 吗。
蚁钳是蚁钳,现在是现在。
你 ******。
由于太中二了,所以就不写下去了。
T3
没改。究其原因是去找 T4 题解了。
T4
记录一下解题思路:
根据不知道叫啥反正是个定理,每个数都可以分解成 。而这个数的因数数量就是 。于是我们就只用关心 了。对于每一个数 都有一个可重集 。其中有 。可以证明一共只有 个不同的 (可惜我不会)。设 为 的最小质因数, 表示把集合 变到有 个因数的最小步数。初始状态 。考虑转移:
为什么可以这么转移呢?因为如果我们想增加因数的个数,无非就是两种方案:新增一个质数或者把某一个原有质数的次数 。显然新增质数更快。所以我们就需要 次操作。
现在考虑 的转移。根据刚刚的结论,可以得出如果存在质因数 只在 中出现且是次数最小的,那么用它转移 是最优的,花费为其出现次数。
那如果没有 怎么办,也很简单。我们只用修改 最小的质因数,枚举 ,然后用 转移 。
贴一下代码:
#include<bits/extc++.h>
#define int long long
#define vi vector<int>
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn = 1e6 + 5,n = 1e6;
const int maxm = 300,m = 290;
int val[maxn];
vi pr,v[maxn];
map<vi,vi>mp;
void prime()
{
for (int i = 2; i <= n; i++)
{
if (!val[i])
{
pr.push_back(i);
val[i] = i;
}
for (auto j = pr.begin(); j != pr.end() && *j * i <= n; j++)
{
val[*j * i] = *j;
if (i % *j == 0)
break;
}
}
}
signed main()
{
prime();
for (int i = 2; i <= n; i++)
{
v[i] = v[i / val[i]];
if (val[i] != val[i / val[i]])
v[i].push_back(2);
else
v[i].back()++;
}
for (int i = 1; i <= n; i++)
sort(v[i].begin(),v[i].end(),greater<int>());
mp[v[1]].resize(maxm);
mp[v[1]][1] = 0;
for (int i = 2; i <= m; i++)
mp[v[1]][i] = mp[v[1]][i / val[i]] + val[i] - 1;
for (int i = 2; i <= n; i++)
{
if (mp.count(v[i]))
continue;
vi tmp = v[i];
tmp.pop_back();
mp[v[i]].resize(maxm);
for (int j = 1; j <= m; j++)
mp[v[i]][j] = mp[tmp][j] + v[i].back() - 1;
for (int j = 1; j <= m; j++)
for (int k = 1; k * j <= m; k++)
mp[v[i]][j * k] = min({mp[v[i]][j * k],mp[tmp][j] + abs(v[i].back() - k),mp[v[i]][j] + k - 1});
}
int t,x,y;
scanf("%lld",&t);
while (t--)
{
scanf("%lld%lld",&x,&y);
int ans = inf;
vi tmp1 = mp[v[x]],tmp2 = mp[v[y]];
for (int i = 1; i <= m; i++)
ans = min(ans,tmp1[i] + tmp2[i]);
printf("%lld\n",ans);
}
return 0;
}
本文来自博客园,使用 CC BY-NC-SA 4.0 协议。
作者:伊埃斯,转载请注明原文链接:https://www.cnblogs.com/Eous/p/18661908
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步