暑期培训:数论总结

只是单纯记录一下结论和自己的理解,太菜了,证明只能看大佬博客(哭

1.裴蜀定理:对于给定的正整数a,b,方程ax+by=c有解的充要条件为c是gcd(a,b)的整数倍。
定理的推广: 方程ax+by+cz+…+nm=f(其中a,b,c…n,f为整数)有解的充要条件是f为gcd(a,b,c,…,n)的整数倍。

2.扩展欧几里得算法:可以求出两个整数x,y,使其满足ax+by=d,d为gcd(a,b).在此前提下使|x|+|y|最小,算法可以求出一组特解,通解为: x = x + k ∗ b d y = y − k ∗ a d x=x+k*\frac{b}{d}\qquad y=y-k*\frac{a}{d}\quad x=x+kdby=ykda
利用该算法还可求逆元,求a在模p下的逆元,代入exgcd(a,p,d,x,y),如果gcd(a,b)!=1,则不存在逆元。否则逆元为(x+p)%p。

void exgcd(ll a,ll b,ll&d,ll& x,ll& y)
{
  if(!b) 
  {
    d=a,x=1,y=0;
  }
  else
  {
    exgcd(b,a%b,d,y,x);y-=x*(a/b);
  }
}

3.欧拉phi函数:phi(x)表示小于x且与x互质的数的个数。推导利用了容斥定理,还是需要理解一下的。结论: p h i ( n ) = n ∗ ( 1 − 1 p 1 ) ∗ ( 1 − 1 p 2 ) . . . ∗ ( 1 − 1 p k ) phi(n)=n*(1-\frac{1}{p_{1}})*(1-\frac{1}{p_{2}})...*(1-\frac{1}{p_{k}}) phi(n)=n(1p11)(1p21)...(1pk1)
p为n的质因子。

//计算单个值欧拉函数值
int get_phi(int n)
{
  int m=sqrt(n+0.5);
  int ans=n;
  for(int i=2;i<=m;i++)
  {
    if(n%i==0)
    {
      ans=ans/i*(i-1);
      while(n%i==0) n/=i;
    }
  }
  if(n>1) ans=ans/n*(n-1);
  return ans;
}
//利用筛法求1~n的phi值
void get_phi(int n)
{
  phi[1]=1;
  for(int i=2;i<=n;i++)
  {
    if(!phi[i])
    {
      for(int j=i;j<=n;j++)
      {
        if(!phi[j]) phi[j]=j;
        phi[j]=phi[j]/i*(i-1);
      }
    }
  }
}

4.欧拉定理 ∀ a , m ∈ Z + , s . t . g c d ( a , m ) = 1 , 则 一 定 满 足 a ϕ ( m ) ≡ 1 ( M o d m ) 。 ∀ a , m ∈ Z+ , s.t. gcd(a,m)=1,则一定满足 a^{ϕ(m)} ≡ 1 (Mod m) 。 a,mZ+,s.t.gcd(a,m)=1aϕ(m)1(Modm)该定理被称作欧拉定理。由此也可得出 a ϕ ( m ) − 1 a^{ϕ(m)-1} aϕ(m)1为a在模m意义下的逆。
扩展欧拉定理
a b ≡ { a b % ϕ ( m )         ( g c d ( a , m ) = = 1 ) a b             ( g c d ( a , m ) ! = 1 & b < ϕ ( m ) ) a b % ϕ ( m ) + ϕ ( m )   ( g c d ( a , m ) ! = 1 & b ≥ ϕ ( m ) ) ( m o d   m ) a^b \equiv\begin{cases} a^{b%\phi(m)}    (gcd(a,m)==1)\\ a^b       (gcd(a,m) !=1 &b<\phi(m))\\ a^{b%\phi(m)+\phi(m)} (gcd(a,m)!=1&b\geq\phi(m)) \end{cases}(mod  m) ababϕ(m)    (gcd(a,m)==1)ab      (gcd(a,m)!=1b<ϕ(m))abϕ(m)+ϕ(m) (gcd(a,m)!=1bϕ(m))(mod m)
证明当时看的大佬博客:链接

5.卢卡斯定理:Lucas定理用于组合数取模,如对 C n m C_{n}^{m} Cnm取模公式如下:
L u c a s ( n , m , p ) = C n % p m % p × L u c a s ( n / p , m / p , p ) ( 保 证 p 为 素 数 ) Lucas(n,m,p)=C_{n\%p}^{m\%p}×Lucas(n/p,m/p,p ) \quad (保证p为素数) Lucas(n,m,p)=Cn%pm%p×Lucas(n/p,m/p,p)(p)
可用于n,m较大,但模数p较小的情况。注意对于 C n m C_{n}^{m} Cnm若m>n则为0。

ll kx[maxn];//保存阶乘,若多组询问可用一个ky[]数组保存逆
ll C(ll n,ll m,ll p)
{
    if(m>n) return 0;
    else return kx[n]*quickpow(kx[m],p-2,p)%p*quickpow(kx[n-m],p-2,p);
}
ll lucas(int n,int m,int p)
{
    if(m==0) return 1;
    else
    {
        ll ans=lucas(n/p,m/p,p)*C(n%p,m%p,p);
        return ans;
    }
}  

附上洛谷大佬证明:链接
扩展卢卡斯定理:待补

6,中国剩余定理:解决多个同余方程,且模数互质。这个证明看的紫书

ll c[maxn],m[maxn];
void exgcd(ll a,ll b,ll &d,ll &x,ll &y)
{
    if(!b)
    {
        d=a,x=1,y=0;
    }
    else
    {
        exgcd(b,a%b,d,y,x);
        y-=x*(a/b);
    }
}

ll china(int n)
{
    ll M=1,ans=0;
    for(int i=1;i<=n;i++) M*=m[i];
    ll x,y,d;
    for(int i=1;i<=n;i++)
    {
        ll w=M/m[i];
        exgcd(w,m[i],d,x,y);//解wx+m[i]y=1(即gcd(w,m[i]))
        //显然wx%m[i]=1
        ans+=w*(x%M)%M*c[i]%M;
        ans=(ans%M+M)%M;
    }
    //最终答案ans=w1*x1*c1+w2*x2*c2...wn*xn*cn.满足所有同余方程
    //比如余m[1]只有(w1x1)%m[1]=1,其他应为w中含有m1因子都为0
    return ans;
}

扩展中国剩余定理:当多个同余方程模数不互质的时候可用该定理。

ll c[maxn],m[maxn];
ll gcd(ll a,ll b)
{
    if(a<b) swap(a,b);
    return b==0?a:gcd(b,a%b);
}
ll qmul(ll x,ll y,ll p)
{
	ll ans=0;
	while(y)
    {
		if(y&1) ans=(ans+x)%p;
		x=(x<<1)%p; y>>=1;
	}
    return ans;
}
void exgcd(ll a,ll b,ll &d,ll &x,ll &y)
{
    if(!b)
    {
        d=a,x=1,y=0;
    }
    else
    {
        exgcd(b,a%b,d,y,x);y-=x*(a/b);
    } 
}

ll exchina(int n)
{
    ll x,y,d;
    ll M=m[1],ans=(c[1]%m[1]+m[1])%m[1];
    for(int i=2;i<=n;i++)
    {
        exgcd(M,m[i],d,x,y);
        ll b=((c[i]-ans%m[i])%m[i]+m[i])%m[i];
        /*前k-1个通解x=x'+t*M,加入第k个方程,要满足x'+t*M≡c[k](mod m[k])
        相当于解该方程:M*t+m[i]*y=c[k]-x'(可调整为模m[i]意义下的正数)。*/
        if(b%d!=0) return -1;
        x=qmul(x,b/d,m[i]);
        ans+=x*M;//x就是t,相当于满足前k-1个方程的通解公式,同时也是第k个方程的解。
        M*=m[i]/d;
        ans=(ans%M+M)%M;
    }
    return ans;
}

证明附上链接:链接

7BSGS算法:又称大步小步算法

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<set>
#include<queue>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<stack>
#include<map>
using namespace std;
typedef long long ll;
const int maxn=1e5+7;
ll a,b,p;
map<ll,int> op;
ll qmul(ll x,ll y,ll p)
{
    ll ans=0;
    while(y)
    {
        if(y&1)
        {
            ans=(ans+x)%p;
        }
        x<<=1;x%=p;
        y>>=1;
    }
    return ans;
}
ll quickpow(ll x,ll y,ll p)
{
    ll ans=1;
    while(y)
    {
        if(y&1)
        {
            ans=ans*x%p;
        }
        x=x*x%p;
        y>>=1;
    }
    return ans;
}
ll log_mod(ll a,ll b,ll p)
{
    int m=sqrt(p+0.5);
    ll v=quickpow(a,m,p);
    v=quickpow(v,p-2,p); 
    ll e=1;op[1]=0; 
    for(int i=1;i<m;i++)
    {
        e=qmul(e,a,p);
        if(!op.count(e)) op[e]=i;
    }
    for(int i=0;i<m;i++)
    {
        if(op.count(b%p))
        return i*m+op[b];
        b=b*v%p;
    }
    return -1;
}
int main()
{
    scanf("%lld%lld%lld",&p,&a,&b);
    ll ans=log_mod(a,b,p);
    if(ans==-1) printf("no solution\n");
    else printf("%lld\n",ans);
    return 0;
}

8原根
大佬博客
洛谷

9莫比乌斯反演
F ( n ) 和 f ( n ) 为 定 义 在 非 负 整 数 上 的 两 个 函 数 F(n)和f(n)为定义在非负整数上的两个函数 F(n)f(n)
若有 F ( n ) = ∑ d ∣ n f ( d ) F(n)=\sum_{d|n}f(d) F(n)=dnf(d)
f ( n ) = ∑ d ∣ n μ ( d ) F ( ⌊ n d ⌋ ) f(n)=\sum_{d|n}\mu(d)F(\lfloor\frac{n}{d}\rfloor) f(n)=dnμ(d)F(dn)
莫比乌斯函数性质:
1,对于任意正整数n, ∑ d ∣ n μ ( d ) = [ n = 1 ] \sum_{d|n}\mu(d)=[n=1] dnμ(d)=[n=1]([n=1]表示只有当n=1成立时,返回值为1;否则,值为0;
2,对于任意正整数n, ∑ d ∣ n μ ( d ) d = ϕ ( n ) n \sum_{d|n}\frac{\mu(d)}{d}=\frac{\phi(n)}{n} dndμ(d)=nϕ(n)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值