反正你也写不出来题,不如来写日记。
上午
有日记的那天一定有考试。
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 0x3f3f3f3f3f3f3f3fusing 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;}