模数转换
(a+b)%p=(a%p+b%p)%p;
(a-b)%p=(a%p-b%p+p)%p;//加上p是为了放置括号里的是负数
(a*b)%p=(a%p*b%p)%p;
(a/b)%p=(a%p*qpow(b,olhs(p)-2)%p)%p;//只在p与b互质时可以使用
快速幂
ll qpow(ll x,ll y)
{
ll ans=1;
while (y)
{
if (y&1)
ans=(ans*x)%mod;
y>>=1;
x=(x*x)%mod;
}
return ans;
}
线性筛法
const int maxn=6666;
int prime[maxn];
int qwe[maxn];
void qprimes()
{
memset (prime,0,sizeof(prime));
memset (qwe,0,sizeof(qwe));
int tmp=0;
for (int i=2;i<=maxn;i++)
{
if (qwe[i]==0)
qwe[i]=prime[++tmp]=i;
for (int j=1;j<=tmp;j++)
{
if (prime[j]*i>maxn||prime[j]>qwe[i])
break;
qwe[i*prime[j]]=prime[j];
}
}
}
扩展欧拉定理,欧拉降幂
一般记住第一个公式就可以了。配合快速幂食用,口味更佳~
卢卡斯定理
分数取模的步骤:pow_mod(f[kk] * f[nn - kk] % p, p - 2, p) % p
模板:
LL f[maxn]; //N??????? ???
void init(int p)
{
f[0] = 1;
for(int i = 1; i <= p; ++i)
f[i] = f[i-1] * i % p;
}
LL pow_mod(LL a, LL x, int p)
{
LL ret = 1;
a %= p;
while(x)
{
if(x & 1)
{
ret = ret * a % p;
--x;
}
else
{
a = a * a % p;
x >>= 1;
}
}
return ret;
}
LL Lucas(LL n, LL k, int p)
{
LL ret = 1;
while(n && k)
{
LL nn = n % p, kk = k % p;
if(nn < kk)
return 0;
ret = ret * f[nn] * pow_mod(f[kk] * f[nn - kk] % p, p - 2, p) % p;
n /= p;
k /= p;
}
return ret;
扩展欧几里得
扩展欧几里德算法是用来在已知a, b求解一组x,y,使它们满足贝祖等式: ax+by = gcd(a, b) =d(解一定存在,根据数论中的相关定理)。扩展欧几里德常用在求解模线性方程及方程组中。
来源:百度百科
模板:
ll x,y;
ll exgcd(ll a,ll b)
{
if (b==0)
{
x=1;
y=0;
return a;
}
ll gcd=exgcd(b,a%b);
ll tx=y;
ll ty=x-a/b*y;
x=tx;
y=ty;
return gcd;
}
函数返回a,b的最大公约数。x,y是a×x+b×y=gcd(a,b)
的一个特解。
通解:
tx = x + b/gcd(a, b) * n
ty = y - a/gcd(a, b) * n
n为任意整数。
若要求a·x+b·y=C
的解
先验证c%gcd!=0?break:;
如果C不是gcd的倍数 说明没有整数解。
如果c%gcd==0
那么有
tx=c/gcd·(x + b/gcd(a, b) * n)
ty=c/gcd·(y - a/gcd(a, b) * n)
关于逆元
逆元素是指一个可以取消另一给定元素运算的元素
乘法逆元:法逆元,是指数学领域群G中任意一个元素a,都在G中有唯一的逆元a‘,具有性质a×a’=a’×a=e,其中e为该群的单位元
扩展欧几里德还能够求乘法逆元
欧拉函数
线性筛法求欧拉函数
原理:
若( N%a ==0&&(N/a)%a ==0)则有:E(N)= E(N/a)*a;
若( N%a ==0&&(N/a)%a !=0)则有:E(N)= E(N/a)*(a-1);
int prime[maxn];
bool isprime[maxn];
int euler[maxn];
void get_euler(){
int tot=0;
MT(isprime,false);
euler[1]=1;
for (int i=2;i<=maxn;i++){
if (isprime[i]== false) {
prime[++tot]=i;
euler[i]=i-1;
}
for (int j=1;j<=tot&&prime[j]<=maxn/i;j++){
isprime[prime[j]*i]= true;
if (i%prime[j]==0){
euler[i*prime[j]]=prime[j]*euler[i];
break;
} else{
euler[i*prime[j]]=(prime[j]-1)*euler[i];
}
}
}
return;
}
ll olhs (ll x)
{
int ans=1;
for (int i=2; i*i<=x; i++)
{
if (x%i==0)
{
ans*=i-1;
x/=i;
}
while (x%i==0)
{
ans*=i;
x/=i;
}
}
if (x>1)
ans*=x-1;
return ans;
}
可以利用欧拉函数与欧拉定理求除法求模
条件:分母与模数互质
ll qpow(ll x,ll y)
{
ll ans=1;
while (y)
{
if (y&1)
ans*=x;
y>>=1;
x*=x;
}
return ans;
}
ll gcd(ll x,ll y)
{
return y==0?x:gcd(y,x%y);
}
ll olhs (ll x)
{
int ans=1;
for (int i=2; i*i<=x; i++)
{
if (x%i==0)
{
ans*=i-1;
x/=i;
}
while (x%i==0)
{
ans*=i;
x/=i;
}
}
if (x>1)
ans*=x-1;
return ans;
}
ll cfmod(ll x,ll y,ll p)
{
if (gcd(y,p)!=1)
return -1;
ll ans=(x%p*(qpow(y,olhs(p)-1)%mod))%mod;
return ans;
}
推导过程如下:
字丑。。将就看吧。。