逆元及中国剩余定理

关于逆元,从网上看到一句话:“除以一个数再取模等同于乘以这个数的逆元再取模”很好。这可以帮助我们去理解什么是逆元。
要注意:对于逆元,我们都是说一个数x在模p的条件下的逆元是多少。而不是直接去说一个数的逆元是多少。
其次,我们不难得知一个数的逆元有无穷多个,但是我们只需要求得一个数的最小正整数逆元就行了。
另外,一个数在模p的条件下不一定有逆元,x关于p的逆元存在当且仅当x和p互质。

求逆元有两种方法:

在这里插入图片描述
在这里插入图片描述

 //by Judge
 inline ll quick_pow(ll x,rint p){
  ll res=1;
  while(p){
   if(p&1) res=(res*x)%mod;
   x=(x*x)%mod, p>>=1;
  }
  return res;
 }
 inline inv(ll a){
  inv_a=quick_pow(a,mod-2);
  return inv_a;
 }

下面我们不着急讲第二种算法,先来讲讲这种快速模算法的应用:

求 C(n,r) % p 的值 , 其中 p 是大质数(如1e9+7) ,那么最后的答案是: 原式 = n! * (r! * (n-r)!)^(p-2) %p

推导过程:
令temp=r!*(n-r)!
那么:C(n,r)%p=(n!/temp)%p
根据我们上面说过的除以一个数取模等于乘上这个数的逆元再取模。
所以:(n!/temp)%p=(n!*temp逆元)%p
而temp逆元根据我们的蒙哥马利快速幂模可知为temp^(p-2)
故结果为
	n! * (r! * (n-r)!)^(p-2) %p

代码实现:

 //by Judge
 #define ll long long
 const ll mod=; //1e9+7或者其他题目给定的大质数
 inline ll quick_pow(ll x,rint p){
  ll res=1;
  while(p){
   if(p&1) res=(res*x)%mod;
   x=(x*x)%mod, p>>=1;
  }
  return res;
 }
 inline C_mod(rint n,rint m){
  ll a=1,b=1;
  for(rint i=2;i<=n<<1;++i)
   a=(a*i)%mod;
  for(rint i=2;i<=m;++i)
   b=(b*i)%mod;
  for(rint i=2;i<=n-m;++i)
   b=(b*i)%mod;
  return (a*quick_pow(b,mod-2))%mod;
 }

在这里插入图片描述
在这里插入图片描述

代码:

//by Judge
#define ll long long
const int mod=; //同上
 void ex_gcd(ll a,ll b,ll &x,ll &y){
  if(!b){ x=1,y=0; return ; }
  ex_gcd(b,a%b,x,y);
  ll t=x; x=y,y=t-(a/b)*y;
 }
 //当然你也可以这么写,更能体现公式: 
 //  ll X=x,Y=y;
 //  x=Y,y=X-(a/b)*Y;
 inline ll inv(ll a){
  ll inv_a,y;
  ex_gcd(a,mod,inv_a,y);
  return inv_a;
 }

例题poj1006:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述中国剩余定理:

#include<stdio.h>
#define MAX 21252
int main()
{
 int p, e, i, d, n, count = 0;
 while( scanf("%d%d%d%d", &p, &e, &i, &d) != EOF )
 {
                count++;
  if(p == -1 && e == -1 && i == -1 && d == -1)
  {
   break;
        }
  n = ( 5544 * p + 14421 * e + 1288 * i - d ) % MAX;
  if( n <= 0 )   // 范围限制 
  {
   n += 21252;
                }
  printf("Case %d: the next triple peak occurs in %d days.\n", count, n );
 }
 return 0;
}

求5544,14421,1288时用到了求逆元。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值