高速べき乗-高精度のべき乗

序文

この記事では、高速電力の原理と使用法について説明します

1.高速べき乗の定義:

定義:すばやく検索し、ベースをベースexpとして累乗します。つまり、次を検索します。baseexp ;

時間計算量:O(log₂N)

2.高速電力の原理:

アイデア:各ステップで、指数は2つの半分に分割され、対応する底は2乗されます。非常に大きな指数を継続的に減らすことができるだけでなく、実行する必要のあるループの数も減り、表現される最終結果は決して変わりません。

原理:(a * b)%m =((a%m)*(b%m))%m

3つの従来のべき乗:

コードブロック:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

ll Pow1(ll my_base, ll my_exp) {
    
    
	ll ans = 1;
	for (int i = 1; i <= my_exp; i++) ans *= my_base;
	return ans;
}

int main() {
    
    
	ios::sync_with_stdio(false);
	cin.tie(0); //断开同步流 

	ll my_base, my_exp, result;
	clock_t my_start, my_end;

	cin >> my_base >> my_exp;
	my_start = clock();
	//该函数返回值是硬件滴答数
	result = Pow1(my_base, my_exp);
	cout << my_base << "^" << my_exp << "=" << result << endl;
	my_end = clock();
	cout << "time=" << ((double)my_end - my_start) / CLK_TCK << "s" << endl;
	//要换算成秒,需要除以CLK_TCK或者 CLK_TCKCLOCKS_PER_SEC

	return 0;
}

演算結果:
ここに画像の説明を挿入

4つの単純で高速なべき乗:

コードブロック:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

ll Pow2(ll x, ll y) {
    
    
	ll ans = 1, base = x;
	while (y != 0) {
    
    
		if (y % 2 != 0) ans *= base;
		base *= base;
		y /= 2;
	}
	return ans;
}

int main() {
    
    
	ios::sync_with_stdio(false);
	cin.tie(0); //断开同步流 

	ll my_base, my_exp, result;
	clock_t my_start, my_end;

	cin >> my_base >> my_exp;
	my_start = clock();
	//该函数返回值是硬件滴答数
	result = Pow2(my_base, my_exp);
	cout << my_base << "^" << my_exp << "=" << result << endl;
	my_end = clock();
	cout << "time=" << ((double)my_end - my_start) / CLK_TCK << "s" << endl;
	//要换算成秒,需要除以CLK_TCK或者 CLK_TCKCLOCKS_PER_SEC

	return 0;
}

演算結果:
ここに画像の説明を挿入

4つの再帰的な高速べき乗:

コードブロック:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

ll Pow3(ll my_base, ll my_exp) {
    
    
	if (my_exp == 1)return my_base;
	ll ans = Pow3(my_base, my_exp / 2);
	return (my_exp % 2 == 0 ? 1 : my_base) * ans * ans;

}

int main() {
    
    
	ios::sync_with_stdio(false);
	cin.tie(0); //断开同步流 

	ll my_base, my_exp, result;
	clock_t my_start, my_end;

	cin >> my_base >> my_exp;
	my_start = clock();
	//该函数返回值是硬件滴答数
	result = Pow3(my_base, my_exp);
	cout << my_base << "^" << my_exp << "=" << result << endl;
	my_end = clock();
	cout << "time=" << ((double)my_end - my_start) / CLK_TCK << "s" << endl;
	//要换算成秒,需要除以CLK_TCK或者 CLK_TCKCLOCKS_PER_SEC

	return 0;
}

演算結果:
ここに画像の説明を挿入

V.ビット演算による迅速なべき乗:

コードブロック:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

ll Pow3(ll my_base, ll my_exp) {
    
    
	int ans = 1, base = my_base;
	while (my_exp != 0) {
    
    
		if (my_exp & 1 != 0)
		{
    
    
			//逐位获取b的二进制位,遇0累乘
			ans *= base;
		}
		base *= base;
		my_exp >>= 1;
	}
	return ans;
}

int main() {
    
    
	ios::sync_with_stdio(false);
	cin.tie(0); //断开同步流 

	ll my_base, my_exp, result;
	clock_t my_start, my_end;

	cin >> my_base >> my_exp;
	my_start = clock();
	//该函数返回值是硬件滴答数
	result = Pow3(my_base, my_exp);
	cout << my_base << "^" << my_exp << "=" << result << endl;
	my_end = clock();
	cout << "time=" << ((double)my_end - my_start) / CLK_TCK << "s" << endl;
	//要换算成秒,需要除以CLK_TCK或者 CLK_TCKCLOCKS_PER_SEC

	return 0;
}

演算結果:
ここに画像の説明を挿入

6つの高精度の高速べき乗:

コードブロック:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const ll mod = 1e7;   //自定义取模的数据,视数据大小的情况而定

//a ^ b
ll ksm(ll a, ll b, ll mod) {
    
        //time_complex=O(logn)
	ll ans = 1, base = a;
	while (b != 0) {
    
    
		if ((b & 1) != 0) {
    
       //“b & 1”指取b的二进制数的最末位
			ans = (ans * base) % mod;   //累乘,以便随时对ans做出贡献。
		}
		base = (base * base) % mod;
		b >>= 1;    //右移1位,删去最低位。
	}
	return ans;
}

int main() {
    
    
	ios::sync_with_stdio(false);
	cin.tie(0); //断开同步流 

	ll a, b, result;
	clock_t my_start, my_end;

	cin >> a >> b;
	my_start = clock();
	//该函数返回值是硬件滴答数
	result = ksm(a, b, mod); 
	cout << a << "^" << b << "=" << result << endl;
	my_end = clock();
	cout << "time=" << ((double)my_end - my_start) / CLK_TCK << "s" << endl;
	//要换算成秒,需要除以CLK_TCK或者 CLK_TCKCLOCKS_PER_SEC

	return 0;
}

演算結果:
ここに画像の説明を挿入

6、Pythonの高精度の高速べき乗:

コードブロック:

a, b = map(int, input().split())
mod = 10000000
result = pow(a, b, mod)
print("{0}^{1}={2}".format(a, b, result))

演算結果:
ここに画像の説明を挿入

7.実際の戦闘演習:

件名のソース:https
//ac.nowcoder.com/acm/problem/213988
ここに画像の説明を挿入
ここに画像の説明を挿入

プログラムコード:
最初の書き方:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
/*long long qmod(ll a,ll b,int c)
{
    if(b==1) return a;
    if(b&1) return a*qmod(a,b-1,c)%c;
    else
    {
        ll m=qmod(a,b/2,c);
        return m*m%c;
    }
    
} *///用二分还是超时
ll qmod(ll a,ll b,ll c)//快速幂
{
    
    
    int r=1;
    while(b)
    {
    
    
        if(b&1) r=a*r%c;
        a=a*a%c;
        b>>=1; //b的二进制形式删除最后一位
    }
    return r;
}
int main()
{
    
    
    long long a,b,c;
    c=998244353;
    cin>>a>>b;
    if(a>c) a=a%c;
    else
    {
    
    
        ll ans=qmod(b+1,a,c);
        cout<<ans<<endl;
    }
    
    
}

2番目の書き方:

n, m = map(int, input().split())
sum = pow(m+1,n,998244353)
print(sum)

演算結果:
ここに画像の説明を挿入

総括する

この記事では、高速電力の基本的な使用法について説明します。

エラーがある場合は、アドバイスしてください!

おすすめ

転載: blog.csdn.net/ivan_9/article/details/113443451