ArcTan

dfs
随笔 - 16, 文章 - 117, 评论 - 6, 引用 - 0
数据加载中……

中国剩余定理

设m1,m2,...,mk是两两互素的正整数,对于任意的正整数a1,a2,a3,..,ak 同余方程组:
 x≡a1 (mod m1)
 x≡a2 (mod m2)
 ...
 x≡ak (mod mk)
 必有解, 且解可写为
 x≡M1N1a1+MkNkak+....MkNkak (mod m)
 其中 m=m1m2m3....mk
 Mi=m/mi,(1<=i<=k)
 Nj满足MjNj≡1(mod mj),1<=j<=k
即:
      Ni,Mi是对模mi的互为逆元。
http://www.cnblogs.com/walker01/archive/2010/01/23/1654880.html
这篇写得不错哇。
     
中国剩余定理O(nlogn),还算高效率的。
#include<stdio.h>
#include
<string.h>
#include
<math.h>
int a[25],m[25],M[25],N[25];
int gcd_ext(int a,int b,int *x,int *y)
{
    
int d,tmp;
    
if (b==0)
    {
        
*x=1;*y=0;
        
return a;
    }
    d
=gcd_ext(b,a%b,x,y);
    tmp
=*x;*x=*y;*y=tmp-(a/b)**y;
    
return d;
}
long long ChReTheorim(int n)
{
    
int i,x,y;
    
long long ans,mul;
    mul
=1;
    
for (i=1;i<=n ;i++ )
        mul
*=m[i];
    ans
=0;
    
for (i=1;i<=n ;i++ )
    {
        M[i]
=mul/m[i];
        gcd_ext(M[i],m[i],
&x,&y);
        N[i]
=(x+m[i])%m[i];
        ans
=(ans+a[i]*M[i]*N[i]) % mul;
    }
    
return ans;
}

int main()
{
    
int i,n;
    
long long ans;
    
while (scanf("%d",&n)==1)
    {
        mul
=1;
        
for (i=1;i<=n ;i++ )
            scanf(
"%d%d",&a[i],&m[i]);
        ans
=ChReTheorim(n);
        printf(
"%lld\n",ans);
    }
    
return 0;
}
尼玛,看算法上的乘法逆元给看成加法逆元了。我还以为我找到O(n)的算法呢。气死:
   a=a1(mod n1)
   a=a2(mod n2)

   a=(a1*n2*N2+a2*n1*N1) % (n1*n2)
其中
   N1是n1模n2的逆元,N2是n2模n1的逆元。
如此反复迭代,可求解。

long long TongYu(int a1,int n1,int a2,int n2)
{
    
int N1,N2,x,y,ans;
    gcd_ext(n1,n2,
&x,&y);
    N1
=(n2+x) % n2;
    gcd_ext(n2,n1,
&x,&y);
    N2
=(n1+x) % n1;
    printf(
"%d %d\n",N1,N2);
    ans
=(a1*n2*N2+a2*n1*N1) % (n1*n2);
    
return ans;
}
哦,



posted on 2012-04-30 16:34 wangs 阅读(261) 评论(0)  编辑 收藏 引用 所属分类: ACM-数学


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理