文章有问题/////////
快速幂取余
ll ksm(long long x,long long a,long long p){//快速幂取余
ll ans=1;
x=x%p;
while(a>0){
if(a&1){
ans=(ans*x)%p;
}
x=(x*x)%p;
a>>=1;
}
return ans;
}
高精度取模
#include<stdio.stdio.h>
#include<iostream>
#include<string>
using namespace std;
int main(){
string a;
int b;
cin >> a >> b;
int len = a.length();
int ans = 0;
for(int i = 0; i < len; i++){
ans = (ans * 10 + a[i] - '0') % b;
}
printf("%d\n",ans);
return 0;
}
逆元计算/扩展欧几里德算法
#include <iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
long long m,x,y;
using namespace std;
void ggcd(int a,int b){
if(b==0){
x=1;
y=0;
return;
}
else{
ggcd(b,a%b);
long long temp=x;
x=y;//相当于x1=y2
y=temp-(a/b)*y;//相当于y1=x2-(a/b)*y2
}//x即为逆元
}
思考:
(个人理解)
扩展欧几里德算法
欧几里德有一个定理:gcd(a,b)=gcd(b,a%b);
这段程序就是解决(a × x)+(b× y)=gcd(a,b);
扫描二维码关注公众号,回复:
2712309 查看本文章
逆元
求式子(a/b)%m的时候,由于b过大会出现爆精度的现象,有时为了精度也会用b的逆元去求式子。
b的逆元可以看作b在这个式子里的又一个倒数,b的逆元会满足原式=(a×b)%m,但b并不是数学意义上的b的倒数,b的倒数往往是一个小数,而b的逆元不会这样。但是在这里b的逆元又满足这个式子。
同余定理
(a + b) % m = (a % m + b % m) % m
(a * b) % m = ((a % m) * (b % m)) % m
这个好理解QAQ
题目
1. 51nod1256 乘法逆元
给出2个数M和N(M < N),且M与N互质,找出一个数K满足0 < K < N且K * M % N = 1,如果有多个满足条件的,输出最小的。
解:真——求乘法逆元。。代码如下
#include <iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
long long m,x,y;
using namespace std;
void ggcd(int a,int b){
if(b==0){
x=1;
y=0;
return;
}
else{
ggcd(b,a%b);
long long temp=x;
x=y;//相当于x1=y2
y=temp-(a/b)*y;//相当于y1=x2-(a/b)*y2
}
}
int main(){
long long n,h;
scanf("%lld %lld",&n,&m);
ggcd(n,m);
while(x<0){
x=(x+m)%m;
}
printf("%lld\n",x);
return 0;
}
2. 51nod1013 3的幂的和
求:3^0 + 3^1 +...+ 3^(N) mod 1000000007
解:Sn=a1*(1-q^(n+1))/(1-q);q=3,a1=1,化简(q^(n+1)-1)/2;即这个式子对1000000007去余。
先求出2对1000000007的逆元,然后快速幂求q^(n+1)(因为(q^(n+1)太大了,所以在求的过程中一直对1000000007取余,防止爆精度),再-1,乘以2的逆元,最后对1000000007取余;代码如下:
#include <iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
typedef long long ll;
const int mod=1000000007;
long long X,y;
long long gcd(long long a,long long b){//计算逆元
int t,d;
if(b==0){
X=1;
y=0;
return a;
}
d=gcd(b,a%b);
t=X;
X=y;//相当于x1=y2
y=t-(a/b)*y;//相当于y1=x2-(a/b)*y2
return d;
}
ll ksm(long long x,long long a,long long p){//快速幂取余
ll ans=1;
x=x%p;
while(a>0){
if(a&1){
ans=(ans*x)%p;
}
x=(x*x)%p;
a>>=1;
}
return ans;
}
int main(){
long long n;
scanf("%lld",&n);
gcd(2,mod);//2%m 原式化简得(q^(n+1)-1)/ 2%m, 所以求2对mod的逆元;
if(X<0){//
X+=mod;
}
n++;
ll ans=(ksm(3,n,mod)-1)*X%mod;//所以原式就变成了(q^(n+1)-1)×x(逆元)%m;
printf("%lld\n",ans);
return 0;
}