zoukankan      html  css  js  c++  java
  • AT2689 Prime Flip

    传送门

    这个题是真的巧妙
    首先一个很巧妙的思路,差分
    考虑假如(a_i!=a_{i-1}),则(b_i=1),否则(b_i=0)
    这样一来,一个区间的翻转就变成了对于两个数的取反了
    然后我们来考虑一下取反的代价(没错这个题我就只想到了这个)
    1、假如距离是奇质数,只要1步,显然
    2、假如距离是偶数,引用一下哥德巴赫猜想,2步即可
    3、假如距离是奇合数,就是3步(奇质数+偶数)
    显然我们可以把这些(b_i=1)的按照奇偶性分为2组
    组内距离一定是奇数,组与组之间可能是奇质数也可能是奇合数
    但是我们显然需要距离为奇质数最多,所以考虑将两组间距离为奇质数的连边,跑二分图最大匹配
    然后假设最大匹配是(k),两组的size分别是(size1,size2)
    那么答案显然是(ans=k+lfloorfrac{size1-k}{2} floor*2+lfloorfrac{size2-k}{2} floor*2+(size1-k)\%2*3)
    代码:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<queue>
    #include<cmath>
    using namespace std;
    void read(int &x){
        char ch;bool ok;
        for(ok=0,ch=getchar();!isdigit(ch);ch=getchar())if(ch=='-')ok=1;
        for(x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());if(ok)x=-x;
    }
    #define rg register
    const int maxn=210;bool vis[maxn];
    int f[maxn],n,ans,a[maxn],mp[maxn][maxn],b[maxn],tot1,tot2,x[maxn];
    bool check(int x){
        if((!(x&1))||x==1)return 0;
        int n=sqrt(x);
        for(rg int i=2;i<=n;i++)
            if(!(x%i))return 0;
        return 1;
    }
    bool dfs(int x){
        for(rg int i=1;i<=tot2;i++)
            if(!vis[i]&&mp[x][i]){
                vis[i]=1;
                if(!f[i]||dfs(f[i]))return f[i]=x,1;
            }
        return 0;
    }
    int main(){
        read(n);
        for(rg int i=1;i<=n;i++)read(x[i]);
        if(n==1){printf("3
    ");return 0;}
        for(rg int i=1;i<=n;i++){
            if(x[i+1]-x[i]!=1||i==n){
                if((x[i]+1)%2==0)a[++tot1]=x[i]+1;
                else b[++tot2]=x[i]+1;
            }
            if(x[i]-x[i-1]!=1||i==1){
                if(x[i]&1)b[++tot2]=x[i];
                else a[++tot1]=x[i];
            }
        }
        for(rg int i=1;i<=tot1;i++)
            for(rg int j=1;j<=tot2;j++)
                if(check(abs(a[i]-b[j])))mp[i][j]=1;
        for(rg int i=1;i<=tot1;i++){
            memset(vis,0,sizeof vis);
            if(dfs(i))ans++;
        }
        printf("%d
    ",ans+(tot1-ans)/2*2+(tot2-ans)/2*2+(tot1-ans)%2*3);
    }
    
    
  • 相关阅读:
    jQuery中添加自定义或函数方法
    一定要明白采取是哪种提交方式,表…
    基本数据类型
    python之运算符
    Java之递归
    【偏序问题】三维偏序,四维偏序
    【复习笔记】主席树
    【bzoj1901】dynamic ranking(带修改主席树/树套树)
    【bzoj4530】大融合(LCT的子树维护)
    POJ1008 Maya Calendar
  • 原文地址:https://www.cnblogs.com/lcxer/p/10736743.html
Copyright © 2011-2022 走看看