等比数列和的快速求法
等比數列是一種常用的數列
樸素的求和方法是直接每項相加,不會影響取模,代碼也很簡單,但是時間復雜度為o(n),難以令人滿意
于是我們想到了通項公式
我們知道,等比數列和前n項和公式為(a1-a1*q^n)/(1-q).
而通過二分計算快速冪可以在log(n)的時間計算出q^n的值,(代碼如下)。剩下的貌似就是簡單的除法了
int pow2( int a, int b ) {int r = 1, base = a;while( b != 0 ){if( b % 2 )r = (r*base)%mod;base =( base*base)%mod;b /= 2;}return r; }?
?
不過事情沒這么簡單。
由于等比數列增加很快,很多題目中我們需要對它進行取模,而通項公式中有除法,不能直接取模,于是我們需要使用數論中講到的模逆元素
?在數論中,若 (a/x) %p= ( a *y%p) 我們稱y為x模p的逆元素
逆元素存在條件為gcd(x,p)=1;
有結論為,若y為x模p的逆元素,則x*y%p=1.
即x*y與1關于p同余
因此我們可以使用exgcd求得x模p的逆元素exgcd(x,p,&y,&z);
得到一個y,若y為負,調整為正數
求得了x的逆元素,我們就可以通過
(a1*pow(q,n)-1)*y%mod 得到等比數列(a1,q)的前n項和了。
?
** 9.8日補充:
若取模的P非質數,那么gcd(x,p)不一定等于1,此時無法通過exgcd求逆元
取模時還有一個備選公式可以使用:
(A/B)%C=(A%(B*C))/B?(A%B?=?0);
不過要注意b*c可能會溢出,適用范圍不大
?
應用:hdu1452?-----求 2004^x(mod 29)
參考資料 http://blog.csdn.net/luyuncheng/article/details/8017016
ac代碼:
#include<stdio.h> #include<algorithm> using namespace std; #define MAX 200000000 #define ull unsigned long long const int MAXN = 100011; int pow2( int a, int b ) {int r = 1, base = a;while( b != 0 ){if( b % 2 )r = (r*base)%29;base =( base*base)%29;b /= 2;}return r; }int main(){int x;while(scanf("%d",&x)&&x){int a=pow2(2,2*x+1);int b=pow2(3,x+1);int c=pow2(22,x+1);printf("%d\n",( a - 1 ) * (( b - 1 ) * 15) * ( c - 1 ) * 18 % 29);}return 0; }?
?
?
轉載于:https://www.cnblogs.com/lnever/p/3933747.html
總結
以上是生活随笔為你收集整理的等比数列和的快速求法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: webview改变网页宽度
- 下一篇: C语言中的nan和inf使用