[C++] 纯文本查看 复制代码 #include<bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int,int>PII;
int is_prime(int x){
for(int i=2;i<=x/i;i++){
if(x%i==0)return 0;
}
return 1;
}
void solve(){
int n;
cin>>n;
vector f(n+10,vector<int>(5,1e18));//0不修改 1改1 2改偶 3改奇
vector<int>a(n+10);
for(int i=1;i<=n;i++)cin>>a[i];
f[1][1]=f[1][2]=f[1][3]=1,f[1][0]=0;
if(a[1]==1)f[1][1]=0;//本来就是1还改啥
for(int i=1;i<=n;i++){
//对0转移 第i位不修改
if(a[i]%2==0){//是偶数
f[i][0]=min(f[i][0],f[i-1][3]);//前面改奇一定存在可以为质数
if(is_prime(a[i]+a[i-1])){//前面不改看看能不能行
f[i][0]=min(f[i][0],f[i-1][0]);
}
if(is_prime(a[i]+1)){//前面改1看看能不能行
f[i][0]=min(f[i][0],f[i-1][1]);
}
}else{//是奇数
f[i][0]=min(f[i][0],f[i-1][2]);//前面改偶一定存在可以为质数
if(is_prime(a[i]+a[i-1])){//前面不改看看能不能行
f[i][0]=min(f[i][0],f[i-1][0]);
}
if(a[i]==1){//当前是1,前面改1,为2没问题
f[i][0]=min(f[i][0],f[i-1][1]);
}
}
//对1转移 第i位改1 前面可以为1和偶数和不改
f[i][1]=min(f[i][1],f[i-1][1]+1);//前面为1,后面为1肯定可以
f[i][1]=min(f[i][1],f[i-1][2]+1);//前面改偶数,一定存在一个改法可以
if(is_prime(a[i-1]+1)){//当前改1看看能不能行
f[i][1]=min(f[i][1],f[i-1][0]+1);
}
//对2转移 第i位改偶 前面可以为1和奇数和不改
f[i][2]=min(f[i][2],f[i-1][1]+1);//前面为1,后面改偶一定存在一个改法可以
f[i][2]=min(f[i][2],f[i-1][3]+1);//前面改奇数,一定存在一个改法可以
if(a[i-1]%2==1){//前面不改,只有前面为奇数后面改偶才一定存在一个改法
f[i][2]=min(f[i][2],f[i-1][0]+1);
}
//对3转移 第i位改奇 前面可以改偶和不改
f[i][3]=min(f[i][3],f[i-1][2]+1);//前面改偶数,一定存在一个改法可以
if(a[i-1]%2==0){//前面不改,只有前面为偶数后面改奇才一定存在一个改法
f[i][3]=min(f[i][3],f[i-1][0]+1);
}
}
cout<<min({f[n][0],f[n][1],f[n][2],f[n][3]})<<endl;
}
signed main(){
int t=1;ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
// cin>>t;
while(t--)solve();
return 0;
} |