当前位置:编程学习 > C/C++ >>

数论中的基本算法 POJ 1845 SPOJ DIVSUM

扩展欧几里得 求逆元(只要a与b互素,那么就有逆元)
[cpp] 
#include<cstdio> 
#include<cstring> 
#include<cstdlib> 
#include<cmath> 
#define mod 9973 
typedef long long ll; 
void ExGcd(int a,int b,int &x,int &y){ 
    if(b==0){ 
        x=1; 
        y=0; 
        return ; 
    } 
    ExGcd(b,a%b,x,y); 
    int t=x; 
    x=y; 
    y=t-a/b*y; 

int main(){ 
    int t,T,rev,x; 
    int a,b; 
    scanf("%d",&T); 
    for(t=1;t<=T;t++){ 
        scanf("%d %d",&a,&b); 
        ExGcd(b,mod,rev,x); 
        printf("%d\n",((rev*a)%mod+mod)%mod); 
    } 

 

O(n)打素数表

[cpp] 
int pn = 0,prime[MAXN],factor[MAXN];//factor[i]为i的最小素约数 
void get_prime(int n){ 
    int i,j; 
    for(i=1;i<=n;i++) 
        factor[i]=i; 
    for(i=2;i<=n;i++){ 
        if(i==factor[i])prime[pn++]=i; 
        for(j=0;j<pn && prime[j]*i<=n;j++){ 
            factor[i*prime[j]]=prime[j]; 
            if(i%prime[j]==0) 
                break; 
        } 
    } 

POJ 1845 二分(1+x+x^2...+x^n)求和
[cpp]
#include<cstdio> 
#include<cstring> 
#include<cstdlib> 
#include<cmath> 
#define mod 9901 
typedef long long ll; 
const int MAXN=10000; 
int a,b,k; 
int p[MAXN],n[MAXN]; 
ll quick(ll num,ll mi){ 
    ll ans=1; 
    while(mi){ 
        if(mi%2)ans=(ans*num)%mod; 
        num=(num*num)%mod; 
        mi/=2; 
    } 
    return ans%mod; 

ll sum(ll num,ll mi){ 
    if(mi==0)return 1; 
    if(mi%2) 
        return (sum(num,mi/2)*(1+quick(num,mi/2+1)))%mod; 
    return (sum(num,mi/2-1)*(1+quick(num,mi/2+1))+quick(num,mi/2))%mod; 

void factor(int a){ 
    int i; 
    k=0; 
    for(i=2;i*i<=a;){  //sqrt(n)的复杂度分解整数 
        if(a%i==0){ 
            p[k]=i; 
            n[k]=0; 
            while(a%i==0){ 
                n[k]++; 
                a/=i; 
            } 
            k++; 
        } 
        if(i>2)i+=2; 
        else i++; 
    } 
    if(a>1){ 
        p[k]=a; 
        n[k]=1; 
        k++; 
    }     

int main(){ 
    int i; 
    scanf("%d %d",&a,&b); 
    factor(a); 
    int ans=1; 
    for(i=0;i<k;i++) 
        ans=(ans*(sum(p[i],n[i]*b))%mod)%mod; 
    printf("%d\n",ans); 

POJ 1845 逆元的方法
[cpp] 
#include<cstdio> 
#include<cstring> 
#include<cstdlib> 
#include<cmath> 
#define mod 9901 
typedef long long ll; 
const int MAXN=10000; 
int a,b,k; 
int p[MAXN],n[MAXN]; 
 
void ExGcd(int a,int b,int &x,int &y){ 
    if(b==0){ 
        x=1; 
        y=0; 
        return ; 
    } 
    ExGcd(b,a%b,x,y); 
    int t=x; 
    x=y; 
    y=t-a/b*y; 

int reverse(int num){ 
    int rev,x; 
    ExGcd(num,mod,rev,x); 
    return rev; 

ll quick(ll num,ll mi){ 
    ll ans=1; 
    while(mi){ 
        if(mi%2)ans=(ans*num)%mod; 
        num=(num*num)%mod; 
        mi/=2; 
    } 
    return ans%mod; 

ll sum(ll num,ll mi){ 
    if(num%mod==1)    //注意到这种情况不能用逆元,因为num-1与mod不互素 
        return (mi+1)%mod; 
    return (((quick(num,mi+1)-1+mod)%mod)*reverse((num-1)%mod)%mod+mod)%mod; 

void factor(int a){ 
    int i; 
    k=0; 
    for(i=2;i*i<=a;){  //sqrt(n)的复杂度分解整数 
        if(a%i==0){ 
            p[k]=i; 
            n[k]=0; 
            while(a%i==0){ 
                n[k]++; 
                a/=i; 
            } 
          &nb

补充:软件开发 , C++ ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,