21天零基础入门ACM
21天零基础入门ACM之 第4天
快速幂
什么是快速幂
说到快速幂,顾名思义就是快速算出某个数的n次幂,他的方法就是把指数二分,从而达到加快速度的目的。
举个例子:
2
10
2^{10}
210;
可以写成
2
8
2^{8}
28 *
2
2
2^{2}
22
1
0
11
10^{11}
1011;
可以写成
2
8
2^{8}
28 *
2
2
2^{2}
22 *
2
1
2^{1}
21
2
15
2^{15}
215;
可以写成
2
8
2^{8}
28 *
2
4
2^{4}
24 *
2
2
2^{2}
22 *
2
1
2^{1}
21;
把一个n次幂,转化为2的倍数次幂的积
如 10 二进制为 1010 即为 8次幂和4次幂的积
而
2
8
2^{8}
28 即为
2
4
2^{4}
24的平方
由此来快速求幂
快速幂的模板
- 第一种(不取模)
typedef longlong ll;
ll qpow(ll a, ll b) { //a的b次方
ll ans = 1;
while (b) {
if (b & 1) //如果二进制的末尾为1,则ans乘以a 否则跳过
ans *= a;
b >>= 1;
a *= a;
}
return ans;
}
- 第二种(取模)
typedef longlong ll;
ll qpow(ll a, ll b, ll mod) { //a的b次方 结果对mod取模
ll ans = 1;
a %= mod;
while (b) {
if (b & 1)
(ans *= a) %= mod;
b >>= 1;
(a *= a) %= mod;
}
return ans % mod;
}
如果真的实在理解不了快速幂,直接背下来模板也可以。快速幂的模板很死,基本上不需要更改。
例题:
题目1:
链接:https://ac.nowcoder.com/acm/contest/8827/G
思路:
看到样例猜测结果是(m+1)的n次方,冲一发,就过来,嘿嘿😁。
代码如下
#include <bits/stdc++.h>
using namespace std;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define sc(x) scanf("%d",&x)
typedef long long ll; typedef unsigned long long ull; typedef long double ld;
inline ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
inline ll read() { ll s = 0, w = 1; char ch = getchar(); while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); } while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar(); return s * w; }
const int mod=998244353;
const int N=1e5+7;
ll qpow(ll a, ll b) {
ll ans = 1;
while (b) {
if (b & 1)
ans *= a;
b >>= 1;
a *= a;
}
return ans;
}
ll qpow(ll a, ll b, ll mod) {
ll ans = 1;
a %= mod;
while (b) {
if (b & 1)
(ans *= a) %= mod;
b >>= 1;
(a *= a) %= mod;
}
return ans % mod;
}
ll n,m;
int main(){
cin>>n>>m;
cout<<qpow(m+1,n,mod)<<endl;
}
题目2:
链接:https://ac.nowcoder.com/acm/problem/19115
#include <bits/stdc++.h>
using namespace std;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define sc(x) scanf("%d",&x)
typedef long long ll; typedef unsigned long long ull; typedef long double ld;
inline ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
inline ll read() { ll s = 0, w = 1; char ch = getchar(); while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); } while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar(); return s * w; }
ll qpow(ll a, ll b) {
ll ans = 1;
while (b) {
if (b & 1)
ans *= a;
b >>= 1;
a *= a;
}
return ans;
}
ll qpow(ll a, ll b, ll mod) {
ll ans = 1;
a %= mod;
while (b) {
if (b & 1)
(ans *= a) %= mod;
b >>= 1;
(a *= a) %= mod;
}
return ans % mod;
}
const int mod=10007;
const int N=1e5+7;
ll n,m;
int main(){
cin>>n>>m;
if(n&1) cout<<qpow(m-1,n,mod)-m+1<<endl;
else cout<<qpow(m-1,n,mod)+m-1<<endl;
}
题目3
链接:https://ac.nowcoder.com/acm/problem/14718
#include <bits/stdc++.h>
using namespace std;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
typedef long long ll; typedef unsigned long long ull; typedef long double ld;
inline ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
const int mod =1e9+7;
ll qpow(ll a, ll b) {
ll ans = 1;
while (b) {
if (b & 1)
ans *= a;
b >>= 1;
a *= a;
}
return ans;
}
ll qpow(ll a, ll b, ll mod) {
ll ans = 1;
a %= mod;
while (b) {
if (b & 1)
(ans *= a) %= mod;
b >>= 1;
(a *= a) %= mod;
}
return ans % mod;
}
ll n,m;
int main(){
while(cin>>n>>m){
ll ans=qpow(m%mod,n,mod);
ll ans2=(qpow((m-1)%mod,n-1,mod)*(m%mod))%mod;
cout<<(ans-ans2+mod)%mod<<endl;
//cout<<ans<<endl;
}
return 0;
}