取模公式
1)a≡a(mod d)
2)对称性 a≡b(mod d)→b≡a(mod d)
3)传递性 (a≡b(mod d),b≡c(mod d))→a≡c(mod d)
如果a≡x(mod d),b≡m(mod d),则
4)a+b≡x+m (mod d)
5)a-b≡x-m (mod d)
6)a*b≡x*m (mod d )
7)a/b≡x/m (mod d)
8) a≡b(mod d)则a-b整除d
9)a≡b(mod d)则a^n≡b^n(mod d)
10)如果ac≡bc(mod m),且c和m互质,则a≡b(mod m)
模运算的运算规则:
(a + b) mod p = (a mod p + b mod p) mod p (1)
(a - b) mod p = (a mod p - b mod p) mod p (2)
(a * b) mod p = (a mod p * b mod p) mod p (3) //这个是没有除法的
a^b mod p = ((a mod p)^b) mod p (4)
结合率: ((a+b) mod p + c) mod p = (a + (b+c) mod p) mod p (5)
((a*b) mod p * c) mod p = (a * (b*c) mod p) mod p (6)
交换率: (a + b) mod p = (b+a) mod p (7)
(a * b) mod p = (b * a) mod p (8)
分配率: ((a +b) mod p * c) mod p = ((a * c) mod p + (b * c) mod p) mod p (9)
重要定理:若a≡b ( mod p),则对于任意的c,都有(a + c) ≡ (b + c) ( mod p);(10)
若a≡b ( mod p),则对于任意的c,都有(a * c) ≡ (b * c) ( mod p);(11)
若a≡b ( mod p),则对于任意的c,都有ac≡ bc ( mod p); (13)
引申:一个数模p再模p.....==只模一次p
快速幂取模
循环写法
利用乘法模运算的公式
与乘方模运算 推其正确性
long long pow_mod(long long a,long long x,long long p)
{
long long ans=1; //p是取模的数
long long base=a%p;
while(x>0)
{
if(x&1==1)
ans=(ans*base)%p; //if里的条件也可以写成x&1
base=base*base%p;
x=x>>1;
}
return ans;
}
递归写法
long long pow_mod(long long a,long long x,long long p)
{
if(x==0)
return 1;
long long ans=pow_mod(a,x>>1,p);
ans=ans*ans%p;
if(x&1==1)
ans=ans*a%p;
return ans;
}
循环写法比递归写法快
指数用二进制表示就容易理解了
快速幂就是快速算出a^x。
快速幂的原理:二进制 2^10=2^2*2^8
long long pow_mod(long long a,long long x)
{
long long ans=1;
long long base=a; //2^0=1,ans*=a;所以base每次从a开始,然后平方变化,所以base*=base;
while(x!=0)
{
if(x&1==1)
ans*=base;
base*=base;
x>>1;
}
return ans;
}
矩阵快速幂
int n,mod;
int init[4],lastans[4],base[4][4],ans[4][4]; //由n-x的x决定
void mul(int b[4][4],int a[4][4],int tans[4][4])
{
int i,j,k;
int t[4][4];
for(i=0;i<4;i++)
for(j=0;j<4;j++)
{
t[i][j]=0;
for(k=0;k<4;k++)
t[i][j]=(t[i][j]+b[i][k]*a[k][j])%mod; //在答案出取余就好
}
for(i=0;i<4;i++)
for(j=0;j<4;j++)
tans[i][j]=t[i][j]%mod;
}
void pow_mod() //base[][],ans[][],n定成全局变量了
{
int i,j;
init[0]=2;init[1]=4;init[2]=6;init[3]=9; //init是初始列矩阵,初始的f值
memset(base,0,sizeof(base));
memset(ans,0,sizeof(ans));
memset(lastans,0,sizeof(lastans));
base[0][1]=1;base[1][2]=1;base[2][3]=1; // base是初始累乘矩阵
base[3][0]=1;base[3][1]=1;base[3][3]=1;
ans[0][0]=ans[1][1]=ans[2][2]=ans[3][3]=1; //ans一开始是单位阵
while(n>0) //n是次方的次数。
{
if((n&1)==1)
mul(base,ans,ans);
mul(base,base,base);
n=n>>1;
}
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
lastans[i]+=ans[i][j]*init[j]; //在答案出取余就好
}
}
for(i=0;i<4;i++)
lastans[i]%=mod;
}