ACM周训练总结(十二)

ACM周训练总结(十二)

本周继续学习了数论的相关知识

一、逆元

概念
对于a * x≡b(mod m)这个方程如果我们要求解的话其实是比较复杂的,可是如果我们可以求出a * y≡1(mod m)中的y的话,在上面那个方程上同乘以y就可以得到,x=b * y,我们也称y是a在mod m的条件下的逆元,写作x ^ -1。
注意:如果m是p的倍数,那么m在mod p的意义下是没有逆元的。

求解方法:(求解逆元等价于解方程ax+my=1)
1、通过拓展欧几里得求解

int inverse(int a, int b) {
  int x, y;
  extend_gcd(a, b, x, y);
  return x;
 }

2、通过欧拉定理求解

#include<iostream>
#include<cstdio>
using namespace std;
int x,y;
void exgcd(int a,int b)
{
    int k;
    if(b==0)//边界 
    {
        x=1;
        y=0;
        return ;
    }
    exgcd(b,a%b);
    k=x;//因为x和y都会改变,所以我们开个变量储存
    x=y;//直接代入我们的公式 
    y=k-a/b*y;
}
int main()
{
    int a,b;
    scanf("%d %d",&a,&b);//我们要求a*y≡1(mod b) 
    exgcd(a,b);//要求a*x+b*y=gcd(a,b) 
    printf("%d",(x+b)%b);//因为求出来的可能是负数所以我们转化成正数 
    return 0;
} 

3、线性递推
推导:首先我们设p=k * i+r,然后可以知道k * i+r≡0(mod p)(因为k * i+r本身等于p,所以p mod p为0),然后我们两边同乘r^-1 * i ^ -1,就得到k * r ^ -1 +i ^ -1 ≡0(mod p),移项得到i ^ -1≡-k * r ^ -1(mod p),我们可以知道k其实就是p/i下取整,也就是⌊ p/i ⌋,r其实就是p%i,(这个好好想想是重点),所以我们得到公式:i ^ -1≡-⌊ p/i ⌋ * (p%i) ^ -1(mod p)

for (inverse[1] = 1, i = 2; i <= n; ++i)
  inverse[i] = inverse[p%i]*(p - p/i) % p;

注意:间复杂度是O(n)的,如果单单求一个逆元的话是比上面的都慢的,可如果要求多个的话这个就显现出来的优势。
我们线性递推其实就是找出逆元与逆元之间的关系,通过已知的逆元求出未知的逆元。

二、容斥原理

定义:如果被计数的事物有A、B、C三类,那么,A类和B类和C类元素个数总和= A类元素个数+ B类元素个数+C类元素个数—既是A类又是B类的元素个数—既是A类又是C类的元素个数—既是B类又是C类的元素个数+既是A类又是B类而且是C类的元素个数。(A∪B∪C = A+B+C - A∩B - B∩C - C∩A + A∩B∩C)
相关问题错排问题

三、欧拉函数

定义欧拉函数定义

性质:1、对于质数p,φ§=p−1;
2、若p为质数,n=pk,则φ(n)=pk-p^(k-1);
3、积性函数:指对于所有互质的整数a和b有性质f(ab)=f(a)f(b)的数论函数。
4、欧拉函数是积性函数,但不是完全积性函数。若m,n互质,则φ(m*n)=φ(m)*φ(n)
(特殊的,当m=2,n为奇数时,φ(2n)=φ(n);当n>2时,φ(n)是偶数;)

编程实现

/*
特性 :
1.若a为质数,phi[a]=a-1;
2.若a为质数,b mod a=0,phi[a*b]=phi[b]*a
3.若a,b互质,phi[a*b]=phi[a]*phi[b](当a为质数时,if b mod a!=0 ,phi[a*b]=phi[a]*phi[b])
*/
int m[n], phi[n], p[n], nump;
//m[i]标记i是否为素数,0为素数,1不为素数;p是存放素数的数组;nump是当前素数个数;phi[i]为欧拉函数
int main()
{
 phi[1] = 1;
 for (int i = 2; i <= n; i++)
 {
  if (!m[i])//i为素数
  {
   p[++nump] = i;//将i加入素数数组p中
   phi[i] = i - 1;//因为i是素数,由特性得知    
  }
  for (int j = 1; j <= nump && p[j] * i <= n; j++)  //用当前已得到的素数数组p筛,筛去p[j]*i
  {
   m[p[j] * i] = 1;//可以确定i*p[j]不是素数 
   if (i % p[j] == 0) //看p[j]是否是i的约数,因为素数p[j],等于判断i和p[j]是否互质 
   {
    phi[p[j] * i] = phi[i] * p[j]; //特性2
    break;
   }
   else phi[p[j] * i] = phi[i] * (p[j] - 1); //互质,特性3其,p[j]-1就是phi[p[j]]   
  }
 }
}

四、中国剩余定理

(孙子定理)
有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二。问物几何?即,一个整数除以三余二,除以五余三,除以七余二,求这个整数。
实现

int CRT(const int a[], const int m[], int n) {
 int M = 1, ret = 0;
 for (int i = 1; i <= n; ++i) M *= m[i];
 for (int i = 1; i <= n; ++i) {
  int Mi = M / m[i], ti = inv(Mi, m[i]);
  ret = (ret + a[i] * Mi * ti) % M;
 }
 return ret;
 }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值