逆元:在mod m的运算下,像满足
ax%m=1
这样的求解出的x,我们称作a的逆元即
a−1
首先简介费马小定理 传送门
对于p是素数时,任意正整数都有
(xp)%p=x
然后可以推出
(xp−1)%p=1
最后可以变形得到
x−1%p=xp−2
所以我们对于一个数求x^(p-2)就是他的逆元.
拓展欧几里得的做法,也很显然,就是求解ax + km = 1中的x就是a的逆元。
例题zzuli 2180 传送门
这个题就是求一个等比数列的前n项和,直接套用公式,不过在公式最后一部分处罚的时候要求一下逆元
代码如下
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
#include<iostream>
#include<set>
#include<queue>
using namespace std;
typedef long long ll;
const ll mod = (ll)1e9+7;
ll Quick_pow(ll x,ll n){
ll res = 1;
while(n){
if(n&1) res = res%mod*x%mod;
x = x%mod*x%mod;
n = n >> 1;
}
return res;
}
ll extgcd(ll a,ll b,ll &x,ll &y){
ll res = 0;
if(b != 0) {
res = extgcd(b,a%b,y,x);
y -= (a/b)*x;
}else{
x = 1;y = 0;
}
return res;
}
ll mod_inverse(ll a,ll m){
ll x,y;
extgcd(a, m, x, y);
return (m + x%m)%m;//这里是为了保证x是最小的正整数
}
int main(void){
ll k,n,Case = 0;
while(scanf("%lld %lld",&k,&n) != EOF){
printf("Case %lld: ",++Case);
if(k == 1) printf("%lld\n",n+1);
else{
ll p = Quick_pow(k,n+1) - 1;
ll q = k - 1;
// ll x,y;
// ll b = Quick_pow(q,mod-2);
ll add = mod_inverse(q,mod);
printf("%lld\n",(p%mod)*add%mod);
}
}
return 0;
}
/**************************************************************
Problem: 2180
User: zhao5502169
Language: C++
Result: Accepted
Time:0 ms
Memory:1368 kb
****************************************************************/