2023 Hubei Provincial Collegiate Programming Contest(gym104337)A. Prime Magic
题目大意
给出一个数列ai,每次可以选择一个区间[l,r]进行全体+1或全体-1,需要满足区间长度len=r-l+1为奇质数p,且操作过程中ai非负
求最少操作次数使得最终ai不减
n<=2e3,1<=ai<=1e5,Σn<=2e4
题解
ai不减显然要差分,设差分得到b[i],使得最终b[i]>=0;设a[n+1]=b[n]=+inf,a[0]=0,b[0]=a[1]
发现原操作等于选择一个奇质数p,对b[i]+x,b[i+p]-x
注意p是奇质数一开始没有注意,所以i和i+p奇偶性不同,每次选择一对来对bi,bi+p操作(将一个+1移到-1上抵消)
按照正负性将b[i]的位置i分成二分图,正连向负,考虑 从正x连向负y的 边权:
①奇偶异号,且差距为质数p:代价1
②奇偶同号:根据哥德巴赫猜想,可以用两个奇质数解决(2=5-3,4=7-3,也可以解决),代价2
③奇偶异号,且差距不为质数:一个奇质数+哥猜的两个,代价3
连边跑费用流,不知道能不能过
考虑先跑一部分边,跑完之后再加剩下的边跑:
先只加①边,跑费用流(实际是二分图匹配),复杂度
发现此时独立为两个二分图,四个部分跑完之后的剩余个数都是确定的
直接贪心匹配剩下的就好了,优先匹配奇偶同号,剩下的奇偶异号匹配就行了
最后复杂度只取决于①部分,实际m=质数个数*n=
所以总复杂度为
code
ozy写的
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=2005;
const int inf=1e9+7;
int n;
int a[N],b[N];
struct qq{int x,y,z,last;}e[N*N*2];
int num,last[N];
int st,ed;
void init (int x,int y,int z)
{
if (z==0) return ;
// printf("%d %d %d\n",x,y,z);
num++;
e[num].x=x;e[num].y=y;e[num].z=z;
e[num].last=last[x];
last[x]=num;
swap(x,y);z=0;
num++;
e[num].x=x;e[num].y=y;e[num].z=z;
e[num].last=last[x];
last[x]=num;
}
int h[N];
bool Bt ()
{
memset(h,-1,sizeof(h));h[st]=1;
queue<int> q;
q.push(st);
while (!q.empty())
{
int x=q.front();q.pop();
for (int u=last[x];u!=-1;u=e[u].last)
{
int y=e[u].y;
if (e[u].z>0&&h[y]==-1)
{
h[y]=h[x]+1;
q.push(y);
}
}
}
return h[ed]!=-1;
}
int dfs (int x,int f)
{
if (x==ed) return f;
int s1=0;
for (int u=last[x];u!=-1;u=e[u].last)
{
int y=e[u].y;
if (e[u].z>0&&h[y]==h[x]+1&&s1<f)
{
int lalal=dfs(y,min(e[u].z,f-s1));
s1+=lalal;
e[u].z-=lalal;
e[u^1].z+=lalal;
}
}
if (s1==0) h[x]=-1;
return s1;
}
vector<int> pri;
bool check (int x)
{
for (int u=2;u*u<=x;u++)
if (x%u==0)
return false;
return true;
}
int main()
{
int T;
scanf("%d",&T);
while (T--)
{
num=1;memset(last,-1,sizeof(last));
scanf("%d",&n);
pri.clear();
for (int u=3;u<=n;u++)
if (check(u))
pri.push_back(u);
for (int u=1;u<=n;u++) scanf("%d",&b[u]);
a[1]=b[1];
for (int u=2;u<=n;u++) a[u]=b[u]-b[u-1];
a[n+1]=inf;n++;
// for (int u=1;u<=n;u++) printf("%d ",a[u]);
// printf("\n");
st=n+1;ed=st+1;
for (int u=1;u<=n;u++)
{
int tmp=a[u];
if (tmp<0) tmp=-tmp;
if (u&1) init(st,u,tmp);
else init(u,ed,tmp);
for (auto xx:pri)
{
if (u+xx<=n&&(LL)a[u]*a[u+xx]<0)
{
if (u&1) init(u,u+xx,inf);
else init(u+xx,u,inf);
}
}
}
int ans=0;
while (Bt()) ans=ans+dfs(st,inf);
int pos1=0,neg1=0;
for (int u=last[st];u!=-1;u=e[u].last)
{
int y=e[u].y;
// printf("%d %d\n",y,a[y]);
if (a[y]>=0) pos1=pos1+e[u].z;
else neg1=neg1+e[u].z;
}
int pos2=0,neg2=0;
for (int u=last[ed];u!=-1;u=e[u].last)
{
int y=e[u].y;
if (a[y]>=0) pos2=pos2+a[y]-e[u].z;
else neg2=neg2+(-a[y])-e[u].z;
}
//printf("%d %d %d %d %d\n",ans,neg1,pos1,neg2,pos2);
if (pos1>=neg1) ans=ans+2*neg1;
else ans=ans+2*pos1+3*(neg1-pos1);
if (pos2>=neg2) ans=ans+2*neg2;
else ans=ans+2*pos2+3*(neg2-pos2);
printf("%d\n",ans);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构