标签:Prime head int Flip atARC080F 素数 edge match mod
构造一个数组$b_{i}$(初始为0),对于操作$[l_{i},r_{i}]$,令$b_{l_{i}}$和$b_{r_{i}+1}$值异或1,表示$i$和$i-1$的差值发生改变,最终即要求若干个$b_{i}$为1,其余为0
对于一组合法方案,通过重新排列操作的顺序,使得每一次操作都有至少一个修改是$b_{i}$由1变为0,然后进行以下构造:
1.仅有1个$b_{i}$由1变为0(即另一个$b_{i}$是由0变成1),我们将其称之为移动,即将这个$b_{i}$移动到了另一个位置,其中移动的距离必须为奇素数
2.两个都由1变为0,可以看作移动到了与另一个1相同的位置上,那么就可以消除,称之为匹配,显然每一个初始为1的位置出现且仅出现在一个匹配内
根据匹配的独立性,对于一组给定的匹配方式,即求每一对数$(x,y)$相同所需要的最小次数之和,同时由于加减互为逆运算,可以看作由$x$变为$y$(即不移动$y$)
求$x$变为$y$的最小次数,对$x$和$y$分类讨论:
1.$x=y$,答案为0
2.$|y-x|$为奇素数,答案为1
3.$|y-x|$为偶数,根据哥德巴赫猜想,答案为2(特别的,2=5-3)
4.$|y-x|$为其他情况,选择一个比其小的奇素数,剩下的偶数部分再分为两个奇素数,因此答案为3(特别的,1=3+3-5,3和5都为素数,是第2种情况)
对于第1种情况,直接贪心匹配,即对于一个连续的$a_{i}$,只需要记录左端点和右端点+1即可
假设初始为1的位置中,有$x$个奇数,$y$个偶数,然后选择了$k$对奇偶使得差为奇素数,然后对于剩下的显然尽量使用第3种,答案即$k+2(\lfloor\frac{x-k}{2}\rfloor+\lfloor\frac{y-k}{2}\rfloor)+3((x-k)mod\ 2)$
由于$2\lfloor\frac{x-k}{2}\rfloor=x-k-(x-k)mod\ 2$,同时$x-k\equiv y-k(mod\ 2)$(1总数为偶数),因此可以化简为$x+y-k+((x-k)mod\ 2)$
当$k$增大后上式一定单调不减,因此仅连奇素数的边,求最大匹配即可,时间复杂度为$o(n^{2})
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 205 4 #define M 10000005 5 struct ji{ 6 int nex,to; 7 }edge[N*N*2]; 8 vector<int>v; 9 int E,n,x,ans,p[M],vis[M],a[N],head[N],match[N]; 10 void add(int x,int y){ 11 edge[E].nex=head[x]; 12 edge[E].to=y; 13 head[x]=E++; 14 } 15 bool dfs(int k){ 16 if (vis[k])return 0; 17 vis[k]=1; 18 for(int i=head[k];i!=-1;i=edge[i].nex) 19 if ((!match[edge[i].to])||(dfs(edge[i].to))){ 20 match[k]=edge[i].to; 21 match[edge[i].to]=k; 22 return 1; 23 } 24 return 0; 25 } 26 int main(){ 27 for(int i=2;i<M-4;i++){ 28 if (!vis[i])p[++p[0]]=i; 29 for(int j=1;(j<=p[0])&&(i*p[j]<M-4);j++){ 30 vis[i*p[j]]=1; 31 if (i%p[j]==0)break; 32 } 33 } 34 vis[0]=vis[1]=vis[2]=1; 35 scanf("%d",&n); 36 for(int i=1;i<=n;i++){ 37 scanf("%d",&x); 38 a[2*i-1]=x; 39 a[2*i]=x+1; 40 } 41 n*=2; 42 sort(a+1,a+n+1); 43 for(int i=1;i<=n;i++) 44 if (((i==1)||(a[i]!=a[i-1]))&&((i==n)||(a[i]!=a[i+1])))v.push_back(a[i]); 45 n=v.size(),x=0; 46 for(int i=0;i<n;i++) 47 if (v[i]&1)x++; 48 memset(head,-1,sizeof(head)); 49 for(int i=0;i<n;i++) 50 for(int j=0;j<n;j++) 51 if (!vis[abs(v[i]-v[j])])add(i,j); 52 for(int i=0;i<n;i++){ 53 memset(vis,0,sizeof(vis)); 54 ans+=dfs(i); 55 } 56 ans/=2; 57 printf("%d",n-ans+((ans&1)!=(x&1))); 58 }View Code
标签:Prime,head,int,Flip,atARC080F,素数,edge,match,mod 来源: https://www.cnblogs.com/PYWBKTDA/p/14063407.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。