Codeforces1699E Three Days Grace【数学】【DP】
分析:
一开始觉得是二分答案,发现行不通之后改为枚举最小值。
现在我将这若干个数分解,假设分解完之后得到的最小值为,那么我就是要在最小值为的基础上尽量最小化分解的各数的最大值。
考虑DP:设表示在分解结果最小值大于等于的情况下,将分解得到的最大值最小是多少。可以得到如下转移:
或者
注意到这样转移状态数太多了,但是我们发现,只有当是的因子时,的值才会发生变化,所以转移可以进一步优化,只留个有用的状态。
接着,答案就是对每个枚举的,求的最大值即可。
这个求最大值的过程如果倒着用可删堆维护会爆空间,所以考虑正着来。先倒着预处理出来等于多少时,会发生变化就行了。(参考我代码里的update部分)
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 1050000; 5 const int maxm = 5050000; 6 7 int n,m; 8 int a[maxn]; 9 int suf[maxm]; 10 int tab[maxm]; 11 int update[maxm]; 12 13 struct Priority_Queue{ 14 priority_queue<int,vector<int>,less<int> > pq,del; 15 void Push(int now){pq.push(now);} 16 void Del(int now){del.push(now);} 17 int Top(){ 18 while(!del.empty() && pq.top() == del.top()){ 19 pq.pop(); 20 del.pop(); 21 } 22 return pq.top(); 23 } 24 void clear(){ 25 while(!pq.empty()) pq.pop(); 26 while(!del.empty()) del.pop(); 27 } 28 }Q; 29 30 int main(){ 31 int t; scanf("%d",&t); 32 while(t--){ 33 scanf("%d%d",&n,&m); 34 int minn = 1e9,maxx = 0; 35 Q.clear(); 36 for(int i=1;i<=n;i++) { 37 scanf("%d",&a[i]); 38 minn = min(minn,a[i]); 39 maxx = max(maxx,a[i]); 40 } 41 for(int i=1;i<=maxx;i++){ 42 suf[i] = i; 43 tab[i] = 0; 44 update[i] = 0; 45 } 46 for(int i=1;i<=n;i++) tab[a[i]]=1; 47 int ans = 1e9; 48 for(int i=maxx;i>=2;i--){ 49 for(int j=i;1ll*j*i<=maxx;j++){ 50 if(tab[i*j]) update[i+1] = max(update[i+1],suf[i*j]); 51 suf[i*j] = min(suf[i*j],suf[j]); 52 } 53 } 54 for(int i=1;i<=maxx;i++){ 55 if(tab[i]){ 56 update[1] = max(update[1],suf[i]); 57 } 58 } 59 int tot = 0; 60 for(int i=1;i<=minn;i++){ 61 tot = max(tot,update[i]); 62 ans = min(ans,tot-i); 63 } 64 printf("%d\n",ans); 65 } 66 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现