題解 P1050 【循環】
阿新 • • 發佈:2018-06-17
如果 次方 個數字 循環節 空間 div 數據 大小 高精度乘法 **題意分析**:
1.求整數n(1 <= n < $10^{100}$)的後k位的循環節
2.數據規模:1 <= n < $10^{100}$,k <= 100
**算法分析:**
直接枚舉:用高精度乘法計算n的a次方,直到後k位出現循環,這樣做有2個缺點:(1)時間復雜度過大,a的大小無法判斷,可能會很超過MAXN,所以會超時 (2)無法判斷不出現循環的情況
可以發現,如果後k位循環,那麽循環節一定是後k-1位循環的循環節的倍數
證明如下:
設後k位循環節為a1,後k-1位循環的循環節是a2,且
a1=$p*{a2}$+b(p,b是常數)
那麽$n^1$的後k-1位=$n^{a2}$的後k-1位
$n^1$的後k位=$n^{a1}$的後k位->$n^1$的後k-1位=$n^{a1}$的後k-1位
所以n^a2的後k-1位等於$n^{a1}$的後k-1位
因為b不是循環節,所以$n^{(p*a2)}$的後k-1位不等於 $ n^ {(p*a2+b)} $ 的後k-1位
n^(p*a2)的後k-1位等於$n^{a2}$的後k-1位
所以$n^{a2}$的後k-1位不等於$n^{a1}$的後k-1位,這與前式矛盾,
所以我們可以求出後k-1位的循環節,再將後k-1位的循環節作為乘數求後k位的循環節(若$n^a$後k-1位與n的後k-1位相等,那麽$n^{(a-1)}$為求後k位時的乘數),這樣可以保證所枚舉到的數一定是後k-1為循環節的倍數,而且可以大大減少枚舉的數量
可以通過記錄後k位循環節長度是後k-1的循環節的多少倍來求循環節,這樣,枚舉的數就不需要用高精度,最後結果相乘時用高精度
(2)整數的每一位有10種可能,如果某個長度枚舉10次仍然沒有循環的話,根據抽屜原理,因為這10個數中有1個沒取到(就是該循環的一位)那麽就一定出現了重復,也就是產生循環,但這個循環是以這9個數字中某個數開始的而不包括應該循環的那一位,那麽意味著該循環的一位永遠不會循環.那麽這個時候就可以判斷,這個數不會出現循環
這樣做,上面直接枚舉的2個問題都可以有效解決,
**優化**:
因為高精度計算中,計算後k位只需要保存後k位乘積的結果,而k範圍較小,在計算是若判斷大於k位則跳出,這樣,節約了一定時間,同時也可以節約空間(因為結果只需存k位).
如果10次中已經出現循環的數,則可以退出
框架:
for(int k=0;k<n;k++)//枚舉循環的位數k
for(int j=0;j<10;j++)//每一位最多有10種可能
{
a*=p;//做乘法,p是待乘的倍數
a1*=p;//a1記錄下一次的增加的倍數
If(a[k]=s[k])//若第k位產生循環
{
sign=1;//標記產生循環
sol[total++]=j+1;//記錄k位循環節長度是後k-1的循環節的多少倍
p=a;//改變乘數
break;
}
}
題解 P1050 【循環】