【POJ 1845】 Sumdiv (整数唯分+约数和公式+二分等比数列前n项和+同余)
【POJ 1845】 Sumdiv
用的東西挺全 最主要通過這個題學了約數和公式跟二分求等比數列前n項和 另一種小優化的整數拆分?
?整數的唯一分解定理:
????? 隨意正整數都有且僅僅有一種方式寫出其素因子的乘積表達式。
????? A=(p1^k1)*(p2^k2)*(p3^k3)*....*(pn^kn)?? 當中pi均為素數
約數和公式:
對于已經分解的整數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)
用遞歸二分求等比數列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); ->偶數時以n/2為中點二分 中點n/2需額外加上
?? 上式紅色加粗的前半部分恰好就是原式的一半,依舊遞歸求解
知道以上三點就好辦了,代碼量如開掛般少。。。(注意上long long 乘中會爆
代碼例如以下:
#include <iostream> #include <cstdio> #include <cstring> #define mod 9901 #define ll long longusing namespace std;ll pow(ll a,ll b)//高速冪 {ll ans = 1;while(b){if(b&1) ans = ans*a%mod;a = a*a%mod;b >>= 1;}return ans; }ll sum(ll p,ll k)//二分求等比數列前n項和 {if(!k) return 1;if(k&1) return sum(p,k/2)*(1+pow(p,k/2+1))%mod;else return (sum(p,k/2-1)*(1+pow(p,k/2+1))+pow(p,k/2))%mod; }ll make(ll a,ll b)//處理a的分解+答案 {int i;ll cnt,ans = 1;for(i = 2; i*i <= a; )//根號法+奇偶法{cnt = 0;while(a%i == 0){a /= i;cnt++;}if(cnt) ans = ans*sum(i,b*cnt)%mod;if(i == 2) i++;//簡單的奇偶優化else i += 2;}if(a != 1) ans = ans*sum(a,b)%mod;return ans; }int main() {ll a,b;scanf("%lld %lld",&a,&b);printf("%lld\n",make(a,b));return 0; }
轉載于:https://www.cnblogs.com/lytwajue/p/7026300.html
總結
以上是生活随笔為你收集整理的【POJ 1845】 Sumdiv (整数唯分+约数和公式+二分等比数列前n项和+同余)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java第三课,流程控制语句
- 下一篇: hdu 3641 数论 二分求符合条件