• CF482A Diverse Permutation(贪心构造)题解


    这里给出一种构造方法及其证明

    方法:考虑从k开始依次构造差值,即第一个与第二个相差(k),第二个与第三个相差(k-1)。首先假设第一个数为(1),因此我们要把(1+k)放在第二个,那么第三个数应该为(1+k-(k - 1) = 2),第四个为(2+(k - 3) = k - 1),第五个为(k - 1 - (k - 2) = 3),以此类推。

    不难发现,其实整个序列的前半段就是由(1,2,3...)(k + 1, k, k - 1...)插空排列成的,我们只需要设置两个变量(i)(j),分别从(1)开始递增,从(k+1)开始递减就行了。而剩下的就从(k+2)(n)依次排列就行了。

    证明:为什么这样构造是对的呢?

    首先,由于是依次构造差值,所以肯定包含了(k)个差值。我们考虑前半段构造的种植条件,即(i geq j)时,更确切地,就是当(i=j)(i = j + 1)时。因此,前半段的最后一项为(lfloorfrac{k}{2} floor),而后半段的首项为(k+2),它们的差为(frac{k}{2})(frac{k}{2}+1),而这个差值肯定是包含在(1-k)之中的。

    综上,这一构造方法是正确的。

    代码实现

    #include <cstdio>
    
    using namespace std;
    
    const int maxn = 1e5 + 10;
    
    int n,k;
    
    int main(){
        scanf("%d%d", &n, &k);
        int i = 1, j = i + k;
        while(1){
            printf("%d %d ", i ++, j --);
            if(i >= j){
                if(i == j) printf("%d ", i);
                break;
            }
        }
        for(int i = k + 2; i <= n; ++ i) printf("%d ", i);
        printf("
    ");
        return 0;
    }
    
  • 相关阅读:
    种子爆破&[GWCTF 2019]枯燥的抽奖
    Springboot学习笔记(三)
    Springboot学习笔记(二)
    Springboot学习笔记(一)
    深入理解java虚拟机阅读笔记(二)对象是否存活与垃圾收集算法
    深入理解java虚拟机阅读笔记(一)java内存区域
    OOP和AOP的区别
    浅谈对spring的理解
    mybatis逆向工程配置文件
    mybatis中${}和#{}的区别
  • 原文地址:https://www.cnblogs.com/whenc/p/13854625.html
Copyright © 2020-2023  润新知