微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

大数分解模板

1.Miller-rabin 算法(基于费马小定理/Fermat 定理)

作用:通过概率的方式判断素数。有误判概率,通过多次判断可以使误判概率控制在很小范围。

理论基础:如果n是一个奇素数, 将n-1表示成2^s*r的形式(r是奇 数),a 是和n互素的任何整数, 那么a^r≡1(mod n) 或者对某个j(0≤j ≤s -1, j∈Z) 等式 a^(2^j*r) ≡-1(mod n)成立。 这个理论是通过一个事实经由Fermat定理推导而来: n是一个奇素数,则方程x2 ≡ 1 mod n只有±1两个解。

代码实现:

  1. #define LL __int64  
  2. const LL NUM=3;//判断次数,每次误判概率1/2.NUM次误判概率为2^(-num)  
  3. LL check(LL a,LL n,LL x,LL t)//合数返回true  
  4. {  
  5.     LL ret=pow_mod(a,x,n);//a^x%n  
  6.     LL last=ret;  
  7.     for(LL i=1;i<=t;i++)  
  8.     {  
  9.         ret=mult_mod(ret,ret,0); background-color:inherit">//ret^2%n,64位乘法,需要用二进制乘法,类似快速幂。  
  10.         if(ret==1 && last!=1 &&last!=n-1)return true;  
  11.         last=ret;  
  12.     }  
  13.     if(ret!=1)return true;  
  14.     return false;  
  15. }  
  16. bool Miller_rabin(LL n)//Miller_rabin算法,素数返回true  
  17. {  
  18.     if(n<2)return false;  
  19.     if(n==2)return true;  
  20.     if((n&1)==0)return false;  
  21.     LL x=n-1;  
  22.     LL t=0;  
  23.     while((x&1)==0){x>>=1;t++;}  
  24.     for(LL i=0;i<NUM;i++)  
  25.     {  
  26.         LL a=rand()%(n-1)+1;//生成1~n-1的随机  
  27.         if(check(a,n,t))  
  28.             return false;  
  29.     }  
  30.     return true;  
  31. }  

2. Pollard rhos算法:

作用:求解一个数的因子。

原理:设n为待分解的大整数,用某种方法生成a和b,计算p=gcd(a-b,n),直到p不为1或a,b出现循环时为止,若p=n,则说明n是一个素数,否则p为n的一个约数。

算法步骤:选取一个小的随机数x1,迭代生成x[i] = x[i-1]^2+c,一般取c=1,若序列出现循环则退出,计算p=gcd(x[i-1]-x[i],n),若p=1则返回上一步继续迭代,否则跳出迭代过程。若p=n,则n为素数,否则p为n的一个约数,并递归分解p和n/p。

可以在θ(sqrt(p))的期望时间内找到n的一个小因子p。但对于因子很少,因子值很大的大整数n,该方法依然不是很有效。

为了减少反复的次数,算法做了一些改进。该算法用数对(x0,x0)开始,并且用x(i+1)=f(xi) ,迭代计算(x1,x2),(x2,x4),(x3,x6)...(xi,x2i)。在每一次迭代中,我们都应用上述函数式运算(从第二步)第一次计算数对中的第一个元素,第二次计算数对中的第二个元素。

代码实现:

?
    LL Pollard_rho(LL n,LL c)//Pollard_rho算法,找出n的因子  
  1.     LL i=1,j,k=2,y,d,p;  
  2.     x=rand()%n;  
  3.     y=x;  
  4.     while(true)  
  5.         i++;  
  6.         x=(mul_mod(x,n)+c)%n;  
  7.         if(y==x)return n;  
  8.         if(y>x)p=y-x;  
  9.         else p=x-y;  
  10.         d=gcd(p,n);  
  11.         if(d!=1&&d!=n)return d;  
  12.         if(i==k)  
  13.         {  
  14.             y=x;  
  15.             k+=k;  
  16.         }  
  17. }  

例子:hdu 3864

题目代码http://www.voidcn.com/article/p-gmfoltuo-pz.html

3.三维求最大子长方体和(可推广到多维)

?
    #include <cstdio>  
  1. #include <cstring>  
  2. #include <cmath>  
  3. #include <cstdlib>  
  4. #include <iostream>  
  5. #include <algorithm>  
  6. #include <queue>  
  7. #include <map>  
  8. #include <set>  
  9. #include <vector>  
  10. #include <cctype>  
  11. using namespace std;  
  12.   
  13. #define LL long long  
  14. void expand(int i,int &b0,87); font-weight:bold; background-color:inherit">int &b1,87); font-weight:bold; background-color:inherit">int &b2)  
  15.     b0=i&1;i>>=1;  
  16.     b1=i&1;i>>=1;  
  17.     b2=i&1;  
  18. }  
  19. int sign(int b0,87); font-weight:bold; background-color:inherit">int b1,87); font-weight:bold; background-color:inherit">int b2)  
  20.     return (b0+b1+b2)%2==1?1:-1;  
  21. const int maxn=30;  
  22. const LL INF=1LL<<60;  
  23. LL s[maxn][maxn][maxn];  
  24. LL sum(int x1,87); font-weight:bold; background-color:inherit">int x2,87); font-weight:bold; background-color:inherit">int y1,87); font-weight:bold; background-color:inherit">int y2,87); font-weight:bold; background-color:inherit">int z1,87); font-weight:bold; background-color:inherit">int z2)  
  25.     int dx=x2-x1+1,dy=y2-y1+1,dz=z2-z1+1;  
  26.     LL ss=0;  
  27.     for(int i=0;i<8;i++)  
  28.                  expand(i,b0,b2);  
  29.         ss-=s[x2-b0*dx][y2-b1*dy][z2-b2*dz]*sign(b0,b2);  
  30.     return ss;  
  31. int main()  
  32. int T;  
  33.     scanf("%d",&T);  
  34.     while(T--)  
  35. int a,b,c,b2,z,x1,y1,x2,y2,i,k;  
  36.         scanf("%d%d%d",&a,&b,&c);  
  37.         memset(s,sizeof(s));  
  38.         for(x=1;x<=a;x++)  
  39.             for(y=1;y<=b;y++)  
  40.                 for(z=1;z<=c;z++)  
  41.                     scanf("%lld",&s[x][y][z]);  
  42.                     for(i=1;i<=7;i++)//容斥定理,奇加偶减  
  43.                     {  
  44.                         expand(i,153); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important">                         s[x][y][z]+=s[x-b0][y-b1][z-b2]*sign(b0,248)">                     }  
  45.         LL ans=-INF;  
  46.         for(x1=1;x1<=a;x1++)  
  47.             for(x2=x1;x2<=a;x2++)  
  48.                 for(y1=1;y1<=b;y1++)  
  49.                     for(y2=y1;y2<=b;y2++)  
  50.                     {  
  51.                         LL m=0;  
  52.                         for(z=1;z<=c;z++)  
  53.                         {  
  54.                             LL ss=sum(x1,1,z);  
  55.                             ans=max(ans,ss-m);  
  56.                             m=min(m,ss);  
  57.                         }  
  58.         printf("%lld\n",ans);  
  59.         if(T!=0)printf("\n");  
  60.     return 0;  
  61. /* 
  62. 一个a*b*c的长方体废料块,每个单位废料块有一个价值,求具有最大价值和的子立方体。 
  63. */

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐