L1-006 连续因子 (20 point(s))
-
这题跟前面相比难度骤增,可能因为我不知道怎么分解因数,之前似乎也没写过这种分解因数的题目,质因数可能有,但这题不是质因数,所以没AC麻了。
后面用别人的测试数据才发现,自己从大到小遍历,会存在因数未能完全分解,比如输入 1260 的话,以12分代码思路只能够得到 3 20 21 的因数。但实际 20 应该进一步分解 得到 4 和 5 。
-
看了下别人的代码发现原本思路的错误,理解错题目的描述了。
“求出最长连续因子的个数,并输出最小的连续因子序列” 最长的因子个数没问题,但是最小连续因子错了。
2 3 3 4 3 4 5 4 5 6比如有一堆因子序列,可以看到最长因子个数是 3 ,而最小连续因子呢,之前以为答案是 2 3 ,是以全部连续因子序列中以最小的首元素为依据。
但实际要求的最小连续因子序列是 3 4 5 。意味是在最长连续因子序列中,找到首元素最小的序列输出。
-
试了试从小到大遍历的问题,发现这样的思路还是存在问题。
![image]()
虽然得到了全部因子的序列,但是截断连续因子可能前面是连续,后面也是连续的因子序列,但因为我们只处理了一次,所以后面的就没有处理。比如第一个全部因子序列有 2 3 5 6 7 ,前面 2 3 是连续,后面 5 6 7 也是连续因子。而后面就没有处理所以就被忽略。
-
思考这段代码跟我们原本思路的差异。之前自己写的时候,想先获取 N 的全部因子,然后提取中间连续的因子部分,但就像上面所说,得到的因子不一定是最简的,不能得到正确的结果。
for (int i = 2; i <= sqrt(N); ++i) { int tmp = N, j = i, count = 0; while (tmp % j == 0) tmp /= j++, count++; if (count > maxcount) maxcount = count, start = i; }而别人正确的代码的思路,没有获取 N 全部的因子,只截取其中一部分连续的因子序列。
所以可以看到,当下面这部分代码对 j 判断,不满足 tmp % j == 0 就退出循环,并记录这个序列初始元素 i 和长度 count 。
-
试了下别人的代码后,还有一个地方有疑惑,为什么要判断因子的存在而输出连续序列,如果没有因子就直接输出 N 。
如果我们改变判断的范围,比如原本是遍历到 sqrt(N) 扩大到 N 是不是类似的。
看了别人的文章知道,原来 N 可能是素数,而素数的因子仅仅包含 1 和其本身 N 。所以判断范围仅仅在 sqrt(N) 的话,就不能够遍历到 N 取其作为因子。
而我们不可能循环遍历到 N,因为 sqrt(N) 后面的数都不会作为 N 的因子。同时如果把范围扩大到 N 还会超时。所以直接对这个特殊情况进行特判
-
从这题其实还应该学到一个思路。从别人的代码可以看到没有获取全部的序列,只获取了连续的序列。
那这样获取会不会有问题。比如下一个因子不是属于因子怎么办。从别人的代码可以看到,只需要处理的时候再判断一下就可以了。
#include <bits/stdc++.h>
using namespace std;
int main(){
int maxCnt = 0, N, start;
cin >> N;
for(int i = 2; i <= sqrt(N); i++){
int tmp = N, cnt = 0;
// 找连续因子序列
for(int j = i; tmp % j == 0; j++){
tmp /= j; cnt++;
}
// 更长则更新序列
if(maxCnt < cnt){
maxCnt = cnt;
start = i;
}
}
if(maxCnt){
cout << maxCnt << endl;
for(int i = start; i < start + maxCnt; i++)
cout << (i == start ? "" : "*") << i;
}
else
cout << 1 << endl << N;
}
// 12 points
#include <bits/stdc++.h>
#include <vector>
using namespace std;
int N, maxn = 0;
map<int, vector<int>> minSeq;
void process(vector<int> f){
// 升序
sort(begin(f), end(f));
// 保存前置因子
for(int i = 0; i < f.size(); i++){
vector<int> ans;
int deal = false;
ans.push_back(f[i]);
// 差值为 1 开始保存 直到差值不为 1
for(int j = i; f[j+1] - f[j] == 1 && j + 1 < f.size(); j++){
deal = true;
ans.push_back(f[j+1]);
}
// 如果处理了则更新
if(deal == true){
if(maxn < ans.size())
maxn = ans.size();
// 如果序列首元素相等且长度大于原序列才更新
if(ans.size() > minSeq[ans[0]].size())
minSeq[ans[0]] = ans;
}
}
}
int main(){
cin >> N;
// 从大的因子开始找
for(int i = N; i >= 2; i--){
int n = N, j = i;
vector<int> factor;
for(int j = i; j >= 2 && n != 1; j--){
if(n % j == 0){
factor.push_back(j);
n /= j;
}
}
// N 能够被整除到 1 处理因子
if(n == 1){
//for(auto f: factor) cout << " " << f;
//cout << endl;
process(factor);
}
}
for(auto m: minSeq){
for(auto v: m.second)
cout << " " << v;
cout << endl;
}
int first = 0;
cout << maxn << endl;
auto m = begin(minSeq);
for(auto v: m->second)
cout << (first++ ? "*" : "") << v;
}

浙公网安备 33010602011771号