Codeforces Problem 414A. Mashmokh and Numbers

题目链接:http://codeforces.com/problemset/problem/414/A 

题意: 接收用户输入两个整数  n, k 。输出一个包含 n 个整数的序列:从前往后每次消除两个数,并计算其最大公约数,直到整数序列中数的个数小于 2(1 个或者 0 个)。在消除的过程中计算这些最大公约数的和。如果等于 k , 则赢。否则输。输出任意一个能赢的整数序列。

思路:n 个整数能形成 n / 2 对数据,即有且仅有 n / 2 个 “最大公约数”。如果 n/2 > k 的话,最大公约数全是 1 都不能得到 k ,则输出 -1 ;如果 n/2 == k 的话, 则输出 k 个最大公约数为 1 的整数对;如果 n/2 < k 的话,则说明一定存在某些数对的最大公约数大于 1, 因为是任意一个,我们可以输出一个最大公约数为 l = k - n/2 + 1 的数对,即(l, l*p(p >= 1)),取最小的就是(l, 2*l),然后在输出 n/2 - 1 个最大公约数为1的数对。这里面有个特殊情况是 k = 0, n = 1 即不取数对,就赢了。最大公约数为1的数对可以直接用两个连续的数。观察数据的范围(1 ≤ n ≤ 105; 0 ≤ k ≤ 1081 ≤ ai ≤ 109)可以知道,2*l+1 ~ 10 的个数一定大于n (max 105 ),故可以在生成第一对数后,直接从 2*l + 1 开始往后面写 n-2 个数即可。

代码:

#include <stdio.h>

int main(){
    int n, k, x;
    scanf("%d%d", &n, &k);
    x = n / 2;
    if(x == 0 && k == 0)
        printf("1");
    else if(x > k || x == 0)
        printf("-1");
    else {
        int l = k - x + 1;
        printf("%d %d", l, 2*l);
        l = 2*l + 1;
        n -= 2;
        while(n--)
            printf(" %d", l++);
    }
    return 0;
}

如果要从小的开始写的话,可以从 2~l-1 &&  l+1 ~ 2*l -1 && 2*l + 1 ~ 一直下去,成对进行输出,最后,如果n为奇数,则最后再输出一个 1 ,否则就不用管。相较上面的做法显麻烦。 

代码:

#include <stdio.h>
int main(){
    int n, k, x, i;
    scanf("%d%d", &n, &k);
    x = n / 2;
    if(k == 0 && n < 2){
        printf("1");
        return 0;
    }
    if(k < x || x < 1){
        printf("-1");
        return 0;
    }
    if(k == x){
        for(i = 0; i < n; i++)
            printf("%d ", i+1);
        return 0;
    }
    
    int l = k - (x - 1);
    printf("%d %d", l, 2*l);
    n = n - 2;

    while(n > 1){
        for(i = 2; n > 1&& i+1 < l; i+=2){
            printf(" %d %d", i, i+1);
            n -= 2;
        }
        for(i = l+1; n > 1 && i+1 < 2*l; i+= 2){
            printf(" %d %d", i, i+1);
            n -= 2;
        }
        for(i = 2*l + 1; n > 1; i += 2){
            printf(" %d %d", i, i+1);
            n -= 2;
        }
    }
    if(n == 1)
        printf(" 1");

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值