Codeforces 教育场 Round19 A B 题解

<A>

题意:

给一个数n,再给一个数k,问 n 能否拆成 k 个大于1的整数的乘积。

思路:

这题核心思想是分解质因数,上一篇博客我刚传过分解质因数的板子,大家可以直接套用。下面解释下这题的核心思想为什么是分解质因数,首先每个合数都能拆成若干质数的乘积形式,而每个质数的因子只有1和它本身,所以说,若想把某个数拆分成几个因子相乘的形式,那么当且仅当所分解出来的乘积项最多的时候,每个乘积项都是质数,因为如果分解的乘积项里含有合数因子,那每个合数因子又能拆成若干个质数的乘积,所以全分解成质数乘积才能保证因子最多。如果不理解的话,我举个栗子,28 = 4 * 7,其中4是合数,还可以拆成2 * 2,故 28 = 2 * 2 * 7,就是可分解出最多因子的形式。所以经过如上分析过后,如果因子数 k 大于所能分解出来的质因子的个数(28 = 2 * 2 * 7,里面质因子个数是3,分别是2,2,7,我是这个意思,不是不同的质因子个数,是全体质因子),那么永远无法满足题意,否则那就选 k - 1 个质因子打印,剩下的质因子求乘积再打印即可。

本人AC代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <string>
#include <map>
#include <queue>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 27;
const int Inf = 1e9 + 7;
queue <int> qua;
map <int, int> mp;
int n, k;
int pri[maxn];

int main() {
    cin >> n >> k;
    int t = 0;
    for(int i = 2; i <= sqrt(n); i++) {
        if(n % i == 0) {
            n /= i; t++; pri[t] = i; i--;
        }
    }
    t++;
    pri[t] = n;
    if(t < k) cout << "-1" << endl;
    else if(t == k) {
        for(int i = 1; i < t; i++) printf("%d ", pri[i]);
        printf("%d\n", pri[t]);
    }
    else {
        int mul = 1;
        for(int i = 1; i <= k - 1; i++) printf("%d ", pri[i]);
        for(int i = k; i <= t; i++) mul *= pri[i];
        printf("%d\n", mul);
    }

}


<B>

题意:在一个序列里找一个不一定连续的子序列,使其和为奇数且最大,即求一段序列能产生的最大奇数和。

思路:

首先先将所有的正数累加求和记一个sum,如果sum是奇数,就直接输出,否则,就进行如下操作:

将所有正数存进 z[ ] 数组中,并升序排序;

将所有负数存进 f[ ] 数组中,并降序排列;

之所以这么做,就是让已经求出的sum按照如上排序逐个减去正数,或逐个加上负数

我的意思并不是对sum进行正数的累减或负数的累加,而是减去最小的正数以后,如果是奇数,就保存一下,跳出,如果不是,就把刚减去的加上,再换第二小的,即下一个,依次往后扫,负数同理,具体操作代码如下:

int p1 = sum, p2 = sum;
        for(int i = 1; i <= t1; i++) {
            p1 -= z[i];
            if(p1 & 1) break;
            else p1 += z[i];
        }
        for(int i = 1; i <= t2; i++) {
            p2 += f[i];
            if(p2 & 1) break;
            else p2 -= f[i];

        }

这样你通过不断加负数和不断减正数得到的最终结果就是p1,  p2,然后再进行如下特判即可:

if((p1 & 1) && (p2 & 1)) ans = max(p1, p2);
        else {
            if(p1 & 1) ans = p1;
            else if(p2 & 1) ans = p2;

        }

本人AC代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 7;
queue <int> qua;
map <int, int> mp;
int n;
int a[maxn];
int z[maxn], f[maxn]; //分别存正负元素的数组
int ans;

bool cmp(int x, int y) { return x > y; }

int main() {
    cin >> n;
    int sum = 0;
    for(int i = 1; i <= n; i++) {
        cin >> a[i];
        if(a[i] > 0) sum += a[i];
    }
    if(sum & 1) ans = sum;
    else {
        int t1 = 0, t2 = 0;
        for(int i = 1; i <= n; i++) {
            if(a[i] > 0) {
                t1++; z[t1] = a[i];
            }
            else if(a[i] < 0) {
                t2++; f[t2] = a[i];
            }
        }
        sort(z + 1, z + t1 + 1); //正数升序排
        sort(f + 1, f + t2 + 1, cmp); //负数降序排
        int p1 = sum, p2 = sum;
        for(int i = 1; i <= t1; i++) {
            p1 -= z[i];
            if(p1 & 1) break;
            else p1 += z[i];
        }
        for(int i = 1; i <= t2; i++) {
            p2 += f[i];
            if(p2 & 1) break;
            else p2 -= f[i];
        }
        if((p1 & 1) && (p2 & 1)) ans = max(p1, p2);
        else {
            if(p1 & 1) ans = p1;
            else if(p2 & 1) ans = p2;
        }
    }
    cout << ans << endl;
}



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值