[Arc080F]Prime Flip

Description

你有无限多的“给给全”,编号为1,2,3,...。开始时,第x1,x2,...,xN个“给给全”是躺着的,其它的“给给全”是趴着的 你可以进行一些操作,每个操作大概是这样的: 选择一个不小于3的质数p,然后将连续的p个“给给全”翻过来 你希望让所有“给给全”趴下。请计算完成这一任务所需的最少操作次数

Input

第一行一个正整数N

第二行N个正整数,第i个数表示xi

Output

一个整数表示最小操作步数

Sample Input

Sample #1

2

4 5

Sample #2

9

1 2 3 4 5 6 7 8 9

Sample #3

2

1 10000000

Sample Output

Sample #1

2

Sample #2

3

Sample #3

4

HINT

样例一可以先选择5,并翻转1,2,3,4,5。然后选择3,并翻转1,2,3

\(1\leq N \leq 100\)

\(1\leq x_1\leq x_2\leq ... \leq x_N\leq 10^7\)

试题分析

首先遇到这种翻转的问题,进行差分,因为这样可以把一段区间的操作看成简单的翻转\(i\)和\(i+p\)个状态的操作。

那么我们希望用最小的步骤使其最优,要怎么办呢?

首先列一个表出来,可以得出结论:1格需要翻转3遍,奇质数需要翻转1遍,偶数需要翻转2遍,奇合数需要翻转3遍。

其中结论1为手推,结论2为题目标准操作,结论3是哥德巴赫猜想,结论4是奇合数可以通过减去一个奇质数得到偶数长度。

于是我们就希望尽量先选翻转1遍的奇质数情况,一定是一奇一偶配对,使其配对数最大。

那么到这里做法就很显然了,直接二分图匹配,然后剩下的单算,注意最后剩1格的情况。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm> using namespace std;
#define LL long long inline int read(){
int x=0,f=1; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
const int INF = 2147483600;
const int MAXN = 10000010; bool vis[MAXN+1];int pri[MAXN+1],cnt;
int flo[MAXN+1]; int N;
int sta[2][20010],top[2];
int Next[20010],Node[20010],Root[20010]; inline void init(){
vis[1]=true;
for(int i=2;i<=MAXN;i++){
if(!vis[i]) pri[++cnt]=i;
for(int j=1;j<=cnt&&pri[j]*i*1LL<=MAXN;j++){
vis[i*pri[j]]=true; if(i%pri[j]==0) break;
}
} return ;
}
int fa[200010];
inline bool dfs(int k){
for(int x=Root[k];x;x=Next[x]){
int v=Node[x];
if(!vis[v]){
vis[v]=true;
if(fa[v]==-1||dfs(fa[v])){
fa[v]=k; return true;
}
}
} return false;
}
inline void insert(int u,int v){
Node[++cnt]=v; Next[cnt]=Root[u]; Root[u]=cnt; return ;
} int main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
for(int i=0;i<=MAXN;i++) flo[i]=1; N=read();
for(int i=1;i<=N;i++){
int x=read(); flo[x]=0;
} init(); for(int i=MAXN;i>=1;i--) {
flo[i]=flo[i]-flo[i-1];
if(flo[i]){
sta[i&1][++top[i&1]]=i;
}
}
for(int i=1;i<=top[0];i++){
for(int j=1;j<=top[1];j++){
if(!vis[abs(sta[0][i]-sta[1][j])]){
insert(i,j+top[0]);
//insert(j+top[0],i);
}
}
} int ans=0;
memset(fa,-1,sizeof(fa));
for(int i=1;i<=top[0];i++){
memset(vis,false,sizeof(vis));
ans+=dfs(i);
}
printf("%d\n",ans+(top[0]-ans)/2*2+(top[1]-ans)/2*2+((top[0]-ans)&1)*3LL);
return 0;
}

[Arc080F]Prime Flip的更多相关文章

  1. 【arc080F】Prime Flip

    Portal --> arc080_f Solution ​  这题的话..差分套路题(算吗?反正就是想到差分就很好想了qwq) ​​  (但是问题就是我不会这种套路啊qwq题解原话是:&quo ...

  2. 【ARC080F】Prime Flip 差分+二分图匹配

    Description ​ 有无穷个硬币,初始有n个正面向上,其余均正面向下.  你每次可以选择一个奇质数p,并将连续p个硬币都翻转.  问最小操作次数使得所有硬币均正面向下. Input ​ 第一行 ...

  3. Prime Flip AtCoder - 2689

    发现我们每次区间取反,相邻位置的正反关系只有两个位置发生改变 我们定义bi为ai和ai-1的正反关系,即ai=ai-1时bi=0,否则bi=1,每次取反l~r,b[l]和b[r+1]会发生改变 容易发 ...

  4. AT2689 [ARC080D] Prime Flip

    简要题解如下: 区间修改问题,使用差分转化为单点问题. 问题变成,一开始有 \(2n\) 个点为 \(1\),每次操作可以选择 \(r - l\) 为奇质数的两个点 \(l, r\) 使其 ^ \(1 ...

  5. 【Atcoder】ARC 080 F - Prime Flip

    [算法]数论,二分图最大匹配 [题意]有无限张牌,给定n张面朝上的牌的坐标(N<=100),其它牌面朝下,每次操作可以选定一个>=3的素数p,并翻转连续p张牌,求最少操作次数使所有牌向下. ...

  6. AT2689 Prime Flip

    传送门 这个题是真的巧妙 首先一个很巧妙的思路,差分 考虑假如\(a_i!=a_{i-1}\),则\(b_i=1\),否则\(b_i=0\) 这样一来,一个区间的翻转就变成了对于两个数的取反了 然后我 ...

  7. [atARC080F]Prime Flip

    构造一个数组$b_{i}$(初始为0),对于操作$[l_{i},r_{i}]$,令$b_{l_{i}}$和$b_{r_{i}+1}$值异或1,表示$i$和$i-1$的差值发生改变,最终即要求若干个$b ...

  8. AtCoder刷题记录

    构造题都是神仙题 /kk ARC066C Addition and Subtraction Hard 首先要发现两个性质: 加号右边不会有括号:显然,有括号也可以被删去,答案不变. \(op_i\)和 ...

  9. Codeforces & Atcoder神仙题做题记录

    鉴于Codeforces和atcoder上有很多神题,即使发呆了一整节数学课也是肝不出来,所以就记录一下. AGC033B LRUD Game 只要横坐标或者纵坐标超出范围就可以,所以我们只用看其中一 ...

随机推荐

  1. Hibernate数据连接不能正常释放的原因,以及在监听中获取apolicationContext上下文

    Hibernate数据库连接不能正常释放: https://blog.csdn.net/u011644423/article/details/44267301 监听中获取applicationCont ...

  2. lua 闪电特效

    闪电特效 根据不同的起点 终点 资源做倾斜 拉伸 ,主要是计算倾斜角度. function ZyLight:show(params) local params = params or {} local ...

  3. RelativeLayout相对布局中属性值

    android:layout_above="@id/xxx"  --将控件置于给定ID控件之上 android:layout_below="@id/xxx"  ...

  4. js中字符串的操作

    1.length 获取字符串长度 var str = "hello world"; alert(str); 2.索引 通过下标获取字符串指定位置的字符,但是不能改变该索引对应的值 ...

  5. github删除文件夹

    git rm -rf dirgit add .git commit -m 'remove dir'git push origin master //dir是要删除的文件夹路径

  6. Java多态的实现原理

    1.多态的定义:指允许不同类的对象,对同一消息作出响应: 即同一消息可以根据发送对象的不同采用多种不同的行为方式: 2.多态的实现技术:动态绑定: 指在执行期间判断所引用对象的实际类型,根据其实际的类 ...

  7. Collection包结构,与Collections的区别

    Collection 1.Collection是集合类的顶级接口: 2.实现接口和类主要有Set.List.LinkedList.ArrayList.Vector.Stack.Set: Collect ...

  8. Linux-进程间通信(四): 域套接字

    1. 域套接字: (1) 只能用于同一设备上不同进程之间的通信: (2) 效率高于网络套接字.域套接字仅仅是复制数据,并不走协议栈: (3) 可靠,全双工: 2. 域套接字地址结构: struct s ...

  9. java===java基础学习(7)---用户自定义类

    package testbotoo; import java.util.*; public class EmployeeTest { public static void main(String[] ...

  10. python基础===基于requests模块上的协程【trip】

    今天看博客get了一个有趣的模块,叫做 trip     #(pip install  trip) 兼容2.7版本 基于两大依赖包:TRIP: Tornado & Requests In Pa ...