<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;
}