数论总结

总结一波数论基础知识。。。。大佬勿入

拓展欧几里得:

这么水,直接上代码比较方便:

LL ex_gcd(LL a,LL b,LL &x,LL &y) //求解一个方程:ax+by=gcd(a,b)的一组特解。
    {LL x1,y1,d; 
    if(b==0) //若b为0显然此时x=1,y=0
        {x=1;y=0;return a; 
        } 
    d=ex_gcd(b,a%b,x1,y1);//将求解转化为求解方程:bx+(a%b)y=gcd(b,a%b)=gcd(a,b),顺便求一下gcd(a,b)
    x=y1;y=x1-a/b*y1; //将得到的解转化一下。
    return d; 
    }

乘法逆元

定义:记数 x x 在模k意义下的乘法逆元为 x1 x − 1 ,即满足模方程: xx1=1(mod,k) x ∗ x − 1 = 1 ( m o d , k )
逆元在求模数时十分有用。
注:有的数可能没有乘法逆元

求法1:

根据欧拉定理可得:对于任意整数 n n ,均存在:xϕ(n)=1(mod,n)
故: xxϕ(n)1=1(mod,n) x ∗ x ϕ ( n ) − 1 = 1 ( m o d , n ) 所以任意数 x x n意义下的的乘法逆元为: xϕ(n)1 x ϕ ( n ) − 1
用快速幂求解即可。时间复杂度: O(log2n) O ( l o g 2 n )
注:一般只用于 n n 素数时,欧拉函数难得算,但是素数时ϕ(p)=p1,考试时一般用的是素数
~~不用贴代码了吧。。。水的很~~

求法2:

我们将模方程换一个方式写下: xx1=1+kn,n x ∗ x − 1 = 1 + k ∗ n , n 显 然 为 整 数
移项得:

xx1kn=1 x ∗ x − 1 − k ∗ n = 1

其中 x1n x − 1 与 n 为未知数,是不是很像方程:ax+by=1?
于是就可以用拓展欧几里得求解 xkxk x 在 k 下 的 逆 元 , 注 意 x 与 k 如果不互质,要除掉gcd。

组合数

还是解释一下吧:
Cmnnm C n m 为 在 n 个 元 素 中 选 取 m 个 个 元 素 出 来 且 不 考 虑 元 素 的 排 列 顺 序 的 方 案 数

Cmn=n!/(m!(nm)!)=Cmn1+Cm1n1=Cm1nnm+1/m C n m = n ! / ( m ! ∗ ( n − m ) ! ) = C n − 1 m + C n − 1 m − 1 = C n m − 1 ∗ ( n − m + 1 ) / m

好了就这样吧。

求法1:数据小时打表啦

用递推式递推即可。

for(i=0;i<=2000;i++)c[i][0]=1;
    for(i=1;i<=2000;i++)
        for(LL j=1;j<=i;j++)
            c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
求法2,求解的组合数中有炒鸡大的数,比模数还大:卢卡斯定理

卢卡斯定理很难说,直接上代码:

LL lucas(int x,int y){
    if(x<mod&&y<mod)return C(x,y);
    return (C(x%mod,y%mod)+C(x/mod,y/mod))%mod;
} 

很简单对不对?剩下的可以用打表法预处理或者预处理阶乘求解即可。

求法3没有办法的办法:线性求C:

根据 Cmn=Cm1nnm+1/m C n m = C n m − 1 ∗ ( n − m + 1 ) / m 线性求,时间复杂度 O(n) O ( n ) ,如果要取余还要求个逆元就是 O(nlog2n) O ( n l o g 2 n )

void getc(int x,int y){
    LL i,ans=1;
    for(i=1;i<=x;i++)ans=((ans*(y-i+1))%mod*getni(i))%mod;
}

欧拉线性筛模板

还是看代码吧:在莫比乌斯反演中非常有用

int pi[100010],prime[100010];
bool mark[100010]
void getpi(){//欧拉线性筛,求解欧拉函数与质数
    int cnt=0,i,j;
    for(i=2;i<=n;i++){
        if(!mark[i]){
            prime[++cnt]=i;//若当前数没被筛到,则它是质数。
            pi[i]=i-1;//质数的欧拉函数是该数减1 
            }
        for(j=0;j<cnt&&i*prime[j]<=n){
            mark[i*prime[j]]=true;
            if(i%prime[j]==0){
                pi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
            else pi[i*prime[j]]=phi[i]*(prime[j]-1);//分类讨论枚举 
        }
    }
}

时间复杂度 O(n) O ( n ) 时间用的很少的暴力筛。

顺便一提:欧拉函数与欧拉定理

欧拉函数: ϕ(n) ϕ ( n ) 为比n小且与n互质的数字个数。它的性质多得不得了。
欧拉定理:

xϕ(n)=1(mod,n) x ϕ ( n ) = 1 ( m o d , n )

这个没多大用处的。但是,它可以压缩快速幂的计算复杂度:
ab=ab%ϕ(k)(mod,k),gcd(a,p)=1 a b = a b % ϕ ( k ) ( m o d , k ) , g c d ( a , p ) = 1

条件太苛刻了,于是又有拓展:
ab=ab%ϕ(k)+ϕ(k)(mod,k) a b = a b % ϕ ( k ) + ϕ ( k ) ( m o d , k )

中国剩余定理:

对于一个数 x x ,对于所有i满足:

x=bi(mod,wi) x = b i ( m o d , w i )

则它的最小正整数解为:
P=n1wi P = ∏ 1 n w i , Mi=P/Wi M i = P / W i , M1i M i − 1 Mi M i 在模 wi w i 意义下的逆元。
x=(Mi×M1i×bi)%P x = ∑ ( M i × M i − 1 × b i ) % P

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值