欢迎来到 @2021zjhs005 的博客园!

快速幂学习笔记

我们不妨先来看一道例题了解一下快速幂:

【模板】快速幂

A template.

观察到数据,a,b231,普通的乘法是肯定不行的。

因此考虑优化:快速幂。

什么是快速幂?

顾名思义,就是快速地求出幂(ab)。

怎么快速地求出幂?

ab 展开,可得:

ab=a×a×a×ab

下面的 b 表示个数啦。

然后将相邻两项合并,得到:

ab=a2×a2×a2×a2b2

这是会消除 b2a,因此还有 b2a

但是 b 可能是奇数,所以需要额外乘一个 a,得到:

ab=a×a2×a2×a2×a2b2

因此,每次操作都会让 bb2,所以时间复杂度为 O(logb),足以通过此题。

如果说 b1010000,那就没办法了,得用更高深的算法(本蒟蒻也不会,qwq)。

代码实现

喜欢用函数的,可以定个 quickpow(a,b)

  • 特判 a=0 的情况,直接返回 0

    • 其实还有一种情况,就是 b=0,但是任何数的 0 次方都等于 1,因此不用顾虑。
  • n>0 才做,用一个 while() 循环。

    • 如果 nmod2=1(是奇数),那么 ans 处理多下的一个 a,也就是 ansans×a

    • 然后 aa2bb2,这就不用解释了吧。

  • 最后返回 ans 即可。

code

#define ll long long
inline ll quick_pow(ll a,ll b) {
	if(!a) return 0;
	ll ans=1;
	while(b){
		if(b&1)//位运算优化。
			ans=ans*a;
		a=a*a;
		b>>=1;//位运算优化 * 2。
	}
	return ans;
}

但这样并不能通过此题,因为 ab 很有可能溢出。

那么就在上面的代码取模一下就行啦:

AC code  局部

#define ll long long
inline ll quick_pow(ll a,ll b,ll p) {
	if(!a) return 0;
	ll ans=1;
	while(b){
		if(b&1) ans=ans*a%p;
		a=a*a%p;
		b>>=1;
	}
	return ans;
}

P10035 「FAOI-R2」Paint (A)

首先打出模拟代码找规律(别的大佬都是证明,就我找规律)。

i 从 1~10 的 answer:


1
4
13
40
121
364
1093
3280
9841
29524

咦,奇怪了,这好像哪里见过,不就是小学奥数的一道经典找规律吗?

递推公式:fi=fi1×3+1

通项公式:fi=(3i1)÷2

3i 次方不就是快速幂吗?

但是除法没有同余性质,所以需要求逆元。 不知道逆元的,建议去这里

代码就简单了:

ll quick_pow(ll x,ll p){//快速幂模板。
	ll res=x,ans=1;	
	while(p){
		if(p&1) ans=ans*res%MOD;
		res=res*res%MOD;
		p>>=1;
	}
	return ans;	
}
int main(){
	cin>>T;
    sum=quick_pow(2,MOD-2);//求逆元。
    while(T--){
        cin>>n;
        ssum=quick_pow(3,n);
        ssum=(ssum-1+MOD)%MOD;
	    cout<<ssum*sum%MOD<<endl;
    }
	return 0;
}

但好像费马小定理有一个条件,不过似乎数据都是 gcd(a,p)=1(doge。


好啦,就到这里吧。

posted @   2021zjhs005  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
记住你学习信息学奥赛的目的,以及梦想。朝着它坚持,这,也是一种美。
点击右上角即可分享
微信分享提示