数论小模版解题报告

一.、快速乘方

此算法解决快速计算Ak这类问题,步骤如下:

1)将k写成二进制数s,s[1]为最低位。

2)假设之前i-1位求出的得数为Ans,如果s[i]位上的数字为1,那么现在的答案就是Ans*A^2^i而A^(i-1)在上一步是能够算出来的。

快速乘方算法其实是一个二分思想,如果对这个还是不太了了解就具体看程序。

 

int QKpower(int a,int k)
{
    int ans=1,temp=a;
    while(k)
    {
          if(k%2)
             ans=ans*temp;
          temp=temp*temp;
          k/=2; 
    }
    return ans;
}


二、 素数筛选

素数也叫质数,即只能被1和自己整除的数。在程序中,怎么筛选出在一定范围中的素数看?我们这样做:

1)、先从2开始找,然后删去这一范围中所有能被2整数的数。

2)、找到下一个没有被删除的数字n。

3)、删去这一范围中所有能整除n的数。

4)、如果n*n>“范围最大值”就跳出,否则跳到第二步。

 

int prime[500000];
void choseprime(int n)
{
     prime[1]=prime[0]=1;
     for(int i=2;i*i<=n;i++)
         if(prime[i]==0)
           for(int j=2*i;j<=n;j+=i)
               prime[j]=1;
}

另一个:

#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
const int M=1000000;
bool is[M];//判断是否为素数 
int prime[M];
int getprime(int n)
{
    int i,j,k=0;
    int s,e=(int)(sqrt(0.0+n)+1);
    memset(is,false,sizeof(is));
    prime[k++]=2;
    is[0]=is[1]=0;
    for(i=4;i<=n;i+=2) is[i]=true;
    for(i=3;i<e;i+=2) if(!is[i]){
        prime[k++]=i;
        for(s=i*2,j=i*i;j<n;j+=s)
           is[j]=true;
    }
    for(;i<n;i+=2) if(!is[i]) prime[k++]=i;
    return k;//n之内的素数个数 
}
int main()
{
    int n,i;
    cin>>n;
    cout<<getprime(n)<<endl;
    for(i=2;i<=n;i++) 
       if(!is[i]) cout<<i<<" ";
    system("pause");
    return 0;
}



 

三、求最大公约数

先看B是否能整除A,如果能整除,直接输出B;如果不能整除,让新A等于原来的B,新B等于原来的A模上原来的B,此时再看B是否能整除A,重复上面步骤即可。

 

int gcd(int a,int b)
{
    if(b==0) return a;
    return gcd(b,a%b);
}


 四、模幂运算

数论中计算中经常出现的一种运算就是求一个整数的幂a^r对另一个数m的模幂运算,既指a^r mod m

(1)、模幂运算1-累次计算法

d=a^r mod m =(…(((((a mod m) * a ) mod m) * a) mod m) … * a) mod m

算法如下:

long modular_power1(long a,long r,long m)
{
     long d=1,i;
     a=a%m;
     for(i=0;i<r;i++)
         d=(a*d)%m;
     return d;
}


(2)、模幂运算2-快速运算法

将r转化成二进制的形式,,然后a反复平方取余。然后将最低位开始,自右至左逐位扫描。每次迭代时,用到下面两个恒等式:

a^2c mod m = (a^2)^c mod m

a^2c+1 mod m =a * (a^2)^c mod m

需计算:a mod m , a^2 mod m , (a^2)^2 mod m ...

算法如下:

long modular_power2(long a,long r,long m)
{
     long d=1,t=a;
     while(r>0)
     {
           if((r%2)==1) d=(d*t)%m;
           r=r/2;
           t=t*t%m;
     }
     return d;
}


 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值