程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> poj 1730 Perfect Pth Powers

poj 1730 Perfect Pth Powers

編輯:C++入門知識

通過這道題確實體會到A掉數學題確實還是需要經驗了,不能猜對哪個地方會喪失精度的話,會一直wa的。其實,這道題我只想出了一半。
題意是 a的p次方 = n,其中n是32位整數,a和p都是整數,求滿足條件的最大p。好吧,雖然我是在學數論,但是看到這題,我還是想起了
取對數。那麼可以得到,p = ln(n) / ln(a)。既然要求最大的p,那麼a最小即可了。那麼直接從2開始枚舉a不就可以了麼。
    可是直接枚舉a的話肯定會超時的,因為a的范圍太大了,比如n的是個大素數,a的范圍就是2-n了,一定超時了。然後,我又想出另外一
種方法,對n分解因子,p就是所有因子的指數的最大公約數。呵呵,第二種方法更加會無情的超時,由於int范圍很大,實現搞個素數表也不
可能。還是感覺時間不多了,就不多想了,然後搜了下,發現一句話,意識是枚舉p。頓時覺得開朗起來,因為p最多是32。由前面可以得到
ln(a) = ln(n) / p。那麼只要從32到1枚舉p,保證a是整數即可。
   後面發現這樣精度難於控制,各種原因反正過不了題,看網上的代碼,改成計算指數的形式了。因為 a = n的(1/p)次,這個可以用pow函
數算出來,如果a是整數,那麼再計算pow(a,p)就會是n了。最難控制的是精度了,還有說n是負數的情況。不知道為什麼直接處理負數答案
一直不對,只好把負數變為正數,同時判斷p不能是偶數。

代碼如下:
#include <stdio.h>
#include <math.h>

int main()
{
    double fN;//用double就不會溢出了,負數就可以直接轉換為正數了
   
    while (scanf("%lf", &fN), fN)
    {
        bool bFlag = false;
        double fP = 31.0;
        if (fN < 0){fP = 32.0; fN = -fN; bFlag = true;};
       
        while (fP > 0)
        {
            //必須加上一個精度,防止往下誤差
            double fA = pow(fN, 1.0 / fP) + 1e-8;
            //fA必須轉換為int,因為一點點誤差,pow之後就會放大很多
            double fTemp = pow((int)fA, fP);
           
            //必須對負數特殊判斷,不可能出現偶數的p
            if (fabs(fN - fTemp) < 1e-8 && (!bFlag || ((int)fP) % 2))
            {
                printf("%.f\n", fP);
                break;
            }
            fP -= 1.0;
        }
    }
   
    return 0;
}
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved