CF1497 E2. Square-free division (hard version)
题意:
有n个正整数,你至多可以把其中k个修改为任意的正整数
你需要把这n个数划分为若干个连续的段,满足每一段的任意两个数的乘积都不是完全平方数
问最少划分为多少段
任意两个数的乘积都不是完全平方数
等价于
把区间内的数质因子分解,每个质因子的指数对2取模,任意两个数的结果都是不同的。
因为可以修改为任意的正整数,所以相当于每个区间内质因子分解指数对2取模的结果至多有k个位置可以与区间内前面的数相同
设dp[i][j]表示前i个数至多修改了j个位置的最少划分段数
枚举最后一段修改了p个位置,假设这最后一段是区间[x,i],那么dp[i][j]可以用dp[x-1][j-p]+1更新
就剩下x怎么求了
预处理le[i][j]表示区间[L,i]至多修改j个数,满足要求的最小的L
这个可以先枚举j,对于每个j用双指针的方法解决
#include<bits/stdc++.h> using namespace std; #define N 200004 int dp[N][21],le[N][21]; int cnt[10000001]; int a[N]; int main() { int T,n,k,x,y,l; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&k); for(int i=1;i<=n;++i) { scanf("%d",&a[i]); x=1; for(int j=2;j*j<=a[i];++j) if(!(a[i]%j)) { y=0; while(!(a[i]%j)) { ++y; a[i]/=j; } if(y&1) x*=j; } a[i]*=x; } for(int i=0;i<=k;++i) { x=0; l=1; for(int r=1;r<=n;++r) { cnt[a[r]]++; if(cnt[a[r]]!=1) ++x; while(x>i) { cnt[a[l]]--; if(cnt[a[l]]) --x; ++l; } le[r][i]=l; } while(l<=n) cnt[a[l++]]--; } for(int i=1;i<=n;++i) for(int j=0;j<=k;++j) dp[i][j]=n; for(int i=1;i<=n;++i) for(int j=0;j<=k;++j) for(int p=0;p<=j;++p) dp[i][j]=min(dp[i][j],dp[le[i][p]-1][j-p]+1); printf("%d\n",dp[n][k]); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架