L1-006 連續因子 (20分)
題目詳情:
題目要求的結果首先得是連續因子,其次因子乘積也得是因子,輸出最長的連續因子,如果長度一樣就輸出最小的連續因子序列。
之前我沒有注意到連續因子乘積也必須是因子,所以測試點3一直通過不了。以1260舉例,它的因子有2 3 4 5 6 7 9 10 12 14 15 18 20 21 28 30 35 36…我最開始覺得是連續因子個數是6因爲2×3×4×5×6×7。但後來我意識到2×3×4×5×6×7=5040>1260,所以我又修改代碼覺得結果是5因爲2×3×4×5×6=720<1260。但我又錯了,因爲1260%720!=0即720並不是1260的因子。正確答案應該是3×4×5,因爲3、4、5首先是1260的因子,其次3、4、5連續,其次乘積也是因子即1260%(3×4×5)==0,所以答案是3和3×4×5。如果輸入6,答案應該是2和2×3。
但這個題測試可能不全,有的代碼不管輸入6的2和2×3還是1和2,提交都AC。比如你把我下面的代碼中的m+1改成m然後輸入6雖然結果是1和2,和m+1的結果2和2×3不一樣,但提交都AC,至少我寫這篇博客是系統是這樣的,說不定以後老師發現了這個bug會修改的。
輸入6,答案應該是2和2×3,也就是判斷是否因子時,m必須加1,因爲int m=sqrt(n),m是整型,整型是向下取整。雖然連續因子肯定不會以sqrt(n)+1打頭,因爲如果是素數,那只有一個因子即本身。如果不是素數,那麼肯定有一個因子在小於等於sqrt(n),如果最長序列爲1的話也是在2~sqrt(n)之中,不可能是sqrt(n)+1;如果最長序列大於1的話,更不可能是以sqrt(n)+1打頭的,因爲sqrt(n)+1乘以下一個因子必大於n。但sqrt(n)+1是有可能包括在前一個因子的序列中,就好比輸入6的這種情況。所以sqrt(n)+1還是要考慮在內的,它後面的因子就不用考慮了,肯定是不可能的,因爲不會有以它們開始的序列的。
分析結束,總之題目一定要好好理解,代碼AC後還要想想自己的思想是否全面,以防判題系統考慮不周。以下是我的AC代碼。
AC代碼:
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
int n,m,i,j,pos,sum,len,mlen=0,t=0;
cin>>n;
m=sqrt(n);
int s[m];
for(i=2; i<=m+1; i++) //連續因子相乘後還是因子,因此符合題意的因子肯定只在2~sqrt(n)+1之間
{
if(n%i==0)
s[t++]=i;
}
if(t==0)//說明是素數
cout<<'1'<<endl<<n<<endl;
else if(t==1)//如果只有一個因數,那麼最長連續因子的個數爲1,最小的連續因子序列就爲s[0]
cout<<'1'<<endl<<s[0]<<endl;
else//大於兩個因數則進入循環
{
for(i=0; i<t-1; i++)
{
sum=s[i];
len=1;
for(j=i; j<t-1; j++)
{
if(s[j+1]-s[j]==1&&n%(sum*s[j+1])==0)//判斷是否連續 連續的話判斷相乘後是否還是因子
{//因爲題目要求的是連續因子,既要連續,連續相乘後還得是因子
sum=sum*s[j+1];
len++;
}
else//不符合直接跳出,判斷以下一個因子開始的序列是否符合
break;
}
if(len>mlen)//如果長度大於最大長度則記錄開始的因子序列
{//如果等於則不變,因爲題目要求輸出的是在序列最長的情況下輸出最小連續因子
mlen=len;//更新最長序列
pos=i;
}
}
cout<<mlen<<endl;//按要求輸出
cout<<s[pos];
for(i=pos+1; i<pos+mlen; i++)
cout<<'*'<<s[i];
cout<<endl;
}
return 0;
}
運行結果:
永遠相信美好🎈