找回密码
 欢迎注册
楼主: wayne

[求助] 组合数的模运算

[复制链接]
 楼主| 发表于 2011-12-29 10:38:15 | 显示全部楼层
7# mathe

mathe可以看一下 原题,我已经追加在主题帖里了
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2011-12-29 10:40:52 | 显示全部楼层
固定数做除数,是有特殊加速算法的,可以用乘以一个固定数再右移固定位数即可,以避免除法指令。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2011-12-29 10:52:49 | 显示全部楼层
6# wayne
这题竟然被我蒙混过关了
准确的说,不是蒙混过关,而是代码很dirty,函数模块封装的不好。
应该在powMod(a,n,MOD);的里面 做 a%=MOD
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2011-12-29 10:55:50 | 显示全部楼层
12# gxqcn
哦,不解。“固定数取模” 就是 我前面说的两个数的乘积的取模吗,
老大可否再透露一点细节,
俺对大数运算,高精度计算,符号运算 还是很感兴趣的,
虽然如此,但一直没有花时间去深入的编程实践,积攒甚少。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2011-12-29 11:30:20 | 显示全部楼层
刚才有点“笔误”,我说的是常数作被除数时有快速算法:


Unsigned division by constant
=============================

enter divisor: 10007

; dividend: register other than EAX or memory location

MOV EAX, 0x68C8C4AD
MUL dividend
SHR EDX, 12

; quotient now in EDX

IMUL EDX, 10007
SUB EAX, EDX

; remainder now in EAX

评分

参与人数 1鲜花 +12 收起 理由
wayne + 12 多谢。

查看全部评分

毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2011-12-29 11:39:26 | 显示全部楼层
汇编呀,
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2011-12-29 19:38:19 | 显示全部楼层
对于M是素数还是比较简单的。先计算分子分母中M次数是否相等,如果不等答案就是0
然后分子分母分别模M相乘,但是遇上M的倍数要先将M因子全除去(而这里由于M已知,不需要每个数都判断,而是可以写成两重循环)。于是得到结果a/b(mod M),
然后对b求数论倒数相乘即可。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2011-12-29 20:13:44 | 显示全部楼层
divid by constant优化通常编译器自己会做
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2011-12-30 12:44:06 | 显示全部楼层
17# mathe
多谢mathe!
简直是 高屋建瓴,势如破竹啊
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2012-1-9 09:39:56 | 显示全部楼层
得空 按mathe的思路实现出来了:
  1. int extendedGCD(int a, int b, int &x, int &y)
  2. {
  3.     /*ax+by=gcd(a,b)*/
  4.     if(b==0)
  5.     {
  6.         x=1;
  7.         y=0;
  8.         return a;
  9.     }
  10.     else
  11.     {
  12.         int s = extendedGCD(b,a%b,x,y);
  13.         int tmp=x;
  14.         x=y;
  15.         y=tmp-(a/b)*y;

  16.         return s;
  17.     }
  18. }

  19. int binomialMod(int k,int n,int mod)
  20. {
  21.     int ii,tmp_k=1,tmp_n=1,g,x_k,y_mod;
  22.     for(ii=0; ii<n; ii++) tmp_k*=k-ii,tmp_k%=mod;
  23.     for(ii=1; ii<=n; ii++) tmp_n*=ii,tmp_n%=mod;
  24.     g=extendedGCD(tmp_n,mod,x_k,y_mod);

  25.     if(x_k<0) x_k+=mod;
  26.     return (tmp_k*x_k)%mod;
  27. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-5-9 08:10 , Processed in 0.070275 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表