等比数列和的快速求法
等比數(shù)列是一種常用的數(shù)列
樸素的求和方法是直接每項(xiàng)相加,不會(huì)影響取模,代碼也很簡(jiǎn)單,但是時(shí)間復(fù)雜度為o(n),難以令人滿意
于是我們想到了通項(xiàng)公式
我們知道,等比數(shù)列和前n項(xiàng)和公式為(a1-a1*q^n)/(1-q).
而通過(guò)二分計(jì)算快速冪可以在log(n)的時(shí)間計(jì)算出q^n的值,(代碼如下)。剩下的貌似就是簡(jiǎ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; }?
?
不過(guò)事情沒(méi)這么簡(jiǎn)單。
由于等比數(shù)列增加很快,很多題目中我們需要對(duì)它進(jìn)行取模,而通項(xiàng)公式中有除法,不能直接取模,于是我們需要使用數(shù)論中講到的模逆元素
?在數(shù)論中,若 (a/x) %p= ( a *y%p) 我們稱y為x模p的逆元素
逆元素存在條件為gcd(x,p)=1;
有結(jié)論為,若y為x模p的逆元素,則x*y%p=1.
即x*y與1關(guān)于p同余
因此我們可以使用exgcd求得x模p的逆元素exgcd(x,p,&y,&z);
得到一個(gè)y,若y為負(fù),調(diào)整為正數(shù)
求得了x的逆元素,我們就可以通過(guò)
(a1*pow(q,n)-1)*y%mod 得到等比數(shù)列(a1,q)的前n項(xiàng)和了。
?
** 9.8日補(bǔ)充:
若取模的P非質(zhì)數(shù),那么gcd(x,p)不一定等于1,此時(shí)無(wú)法通過(guò)exgcd求逆元
取模時(shí)還有一個(gè)備選公式可以使用:
(A/B)%C=(A%(B*C))/B?(A%B?=?0);
不過(guò)要注意b*c可能會(huì)溢出,適用范圍不大
?
應(yīng)用: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; }?
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/lnever/p/3933747.html
總結(jié)
以上是生活随笔為你收集整理的等比数列和的快速求法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: webview改变网页宽度
- 下一篇: C语言中的nan和inf使用