大致題意:
求a^b的所有約數(即因子)之和,並對其取模 9901再輸出。
解題思路:
應用定理主要有三個:
(1) 整數的唯一分解定理:
任意正整數都有且只有一種方式寫出其素因子的乘積表示式。
a=(p1^k1)*(p2^k2)*(p3^k3)*....*(pn^kn) 其中pi均為素數
(2) 約數和公式:
對於已經分解的整數a=(p1^k1)*(p2^k2)*(p3^k3)*....*(pn^kn)
有a的所有因子之和為
s = (1+p1+p1^2+p1^3+...p1^k1) * (1+p2+p2^2+p2^3+….p2^k2) * (1+p3+ p3^3+…+ p3^k3) * .... * (1+pn+pn^2+pn^3+...pn^kn)
(3) 同餘模公式:
(a+b)%m=(a%m+b%m)%m
(a*b)%m=(a%m*b%m)%m
有了上面的數學基礎,那麼本題解法就很簡單了:
1: 對a進行素因子分解
分解a的方法:
a首先對第乙個素數2不斷取模,a%2==0時 ,記錄2出現的次數+1,a/=2;
當a%2!=0時,則a對下乙個連續素數3不斷取模...
以此類推,直到a==1為止。
注意特殊判定,當a本身就是素數時,無法分解,它自己就是其本身的素數分解式。
最後得到a = p1^k1 * p2^k2 * p3^k3 *...* pn^kn.
故 a^b = p1^(k1*b) * p2^(k2*b) *...* pn^(kn*b);
2:a^b的所有約數之和為:
sum = [1+p1+p1^2+...+p1^(a1*b)] * [1+p2+p2^2+...+p2^(a2*b)] *...* [1+pn+pn^2+...+pn^(an*b)].
3: 用遞迴二分求等比數列1+pi+pi^2+pi^3+...+pi^n:
(1)若n為奇數,一共有偶數項,則:
1 + p + p^2 + p^3 +...+ p^n
= (1+p^(n/2+1)) + p * (1+p^(n/2+1)) +...+ p^(n/2) * (1+p^(n/2+1))
=(1 + p + p^2 +...+ p^(n/2))* (1 + p^(n/2+1))
上式加粗的前半部分恰好就是原式的一半,那麼只需要不斷遞迴二分求和就可以了,後半部分為冪次式,將在下面第4點講述計算方法。
(2)若n為偶數,一共有奇數項,則:
1 + p + p^2 + p^3 +...+ p^n
= (1+p^(n/2+1)) + p * (1+p^(n/2+1)) +...+ p^(n/2-1) * (1+p^(n/2+1)) + p^(n/2)
=(1 + p + p^2 +...+ p^(n/2-1))* (1+p^(n/2+1)) + p^(n/2);
上式加粗的前半部分恰好就是原式的一半,依然遞迴求解
4:反覆平方法計算冪次式p^n
這是本題關鍵所在,求n次冪方法的好壞,決定了本題是否tle。
以p=2,n=8為例
常規是通過連乘法求冪,即2^8=2*2*2*2*2*2*2*2
這樣做的要做8次乘法
而反覆平方法則不同,
定義冪sq=1,再檢查n是否大於0,
while,迴圈過程若發現n為奇數,則把此時的p值乘到sq
則sq=256就是所求,顯然反覆平方法只做了3次乘法
//view codememory time
//336k 0ms
#include
using
namespace
std;
const
int size=10000
;const
int mod=9901
;__int64 sum(__int64 p,__int64 n);
//遞迴二分求 (1 + p + p^2 + p^3 +...+ p^n)%mod
__int64 power(__int64 p,__int64 n); //
反覆平方法求 (p^n)%mod
int main(void
) k++;
}if(i==2) //
奇偶法 i++;
else
i+=2
; }
/*特殊判定:分解整數a (a為質數)
*/if(a!=1
)
int ans=1; //
約數和for(i=0;i)
ans=(ans*(sum(p[i],n[i]*b)%mod))%mod; //
n[i]*b可能會超過int,因此用__int64
cout
}return0;
}__int64 sum(__int64 p,__int64 n)
//遞迴二分求 (1 + p + p^2 + p^3 +...+ p^n)%mod
__int64 power(__int64 p,__int64 n)
//反覆平方法求(p^n)%mod
return
sq;}
**自:優you
數論 二分快速取餘
求12345 12345的所有約數 即因子 之和,並對其取模9901再輸出。key格式 ctf 這裡存在三個有趣的數學定理 1 整數唯一分解定理 2 約數和公式 3 同餘模公式 includeusing namespace std const int size 10000 const int mod...
poj 1845 Sumdiv 數論 二分
剛開始學習數論,不知道該從哪方面學起,就找了這道題做做,希望通過做題能找到學習數論的方向。花了有兩天的時間終於弄懂了這題的思想,恩,數論真的很神奇!題意是 求a b的所有因子的和取餘9901後的結果。用到的知識點有 1 素因子分解唯一性定理 任意正整數都能用一種方式且只有一種方式寫出素數的乘積。如 ...
POJ 1845 Sumdiv 質因數分解 二分
關於質因數分解,模板見 二分法思想 選定乙個要進行比較的目標,在區間 l,r 之間不斷二分,直到取到與目標相等的值。include include include using namespace std typedef long long ll const int n 10000 const int...