大整数约数问题

//来自kuangbin的ACM模板

//大整数约数和

/*
POJ 1845 Sumdiv
求A^B的所有约数之和%9901

*/
/*
大整数的约数和 三个问题 
1.约数和结论-对于一个大整数N,他的因数分解式为 ( a1^x1 ) * ( a2 ^ x2) * (a3^x3 )... ,那么约数和 sum = ( 1 + a1 + a1^2 + ... a1^x1 ) *  ( 1 + a2 + a2^2 + ... a2^x2 ) * ...
2.等比数列和的递归表达式:
    1 + p + p^2 + p^3 +...+ p^n
        = (n为奇数时,一共有偶数项)(1 + p + p^2 +...+ p^(n/2)) * (1 + p^(n/2+1))
        = (n为偶数时,一共有奇数项)(1 + p + p^2 +...+ p^(n/2-1)) * (1+p^(n/2+1)) + p^(n/2) 
3.因数分解
*/ 


#include<stdio.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;

#define MOD 9901

//******************************************
//素数筛选和合数分解
const int MAXN=10000;
int prime[MAXN+1];
void getPrime()
{
    memset(prime,0,sizeof(prime));
    for(int i=2;i<=MAXN;i++)
    {
        if(!prime[i])prime[++prime[0]]=i;
        for(int j=1;j<=prime[0]&&prime[j]<=MAXN/i;j++)
        {
            prime[prime[j]*i]=1;
            if(i%prime[j]==0) break;
        }
    }
}
long long factor[100][2];
int fatCnt;
int getFactors(long long x)
{
    fatCnt=0;
    long long tmp=x;
    for(int i=1;prime[i]<=tmp/prime[i];i++)
    {
        factor[fatCnt][1]=0;
        if(tmp%prime[i]==0)
        {
            factor[fatCnt][0]=prime[i];
            while(tmp%prime[i]==0)
            {
                factor[fatCnt][1]++;
                tmp/=prime[i];
            }
            fatCnt++;
        }
    }
    if(tmp!=1)
    {
        factor[fatCnt][0]=tmp;
        factor[fatCnt++][1]=1;
    }
    return fatCnt;
}

//******************************************
long long pow_m(long long a,long long n)//快速模幂运算
{
    long long res=1;
    long long tmp=a%MOD;
    while(n)
    {
        if(n&1){res*=tmp;res%=MOD;}
        n>>=1;
        tmp*=tmp;
        tmp%=MOD;
    }
    return res;
}
//计算1+p+p^2+````+p^n , 计算等比数列的和对mod取模算法 
//等比数列和的递归运算,复杂度O(logN * logN) 
//还可以使用等比数列和公式求解,此处使用等比数列的递推公式求解
long long sum(long long p,long long n)
{
    if(p==0)return 0;
    if(n==0)return 1;
    if(n&1)//奇数
    {
        return ((1+pow_m(p,n/2+1))%MOD*sum(p,n/2)%MOD)%MOD;
    }
    else return ((1+pow_m(p,n/2+1))%MOD*sum(p,n/2-1)+pow_m(p,n/2)%MOD)%MOD;

}
int main()
{
    int A,B;
    getPrime();
    while(scanf("%d%d",&A,&B)!=EOF)
    {
        getFactors(A);
        long long ans=1;
        for(int i=0;i<fatCnt;i++)
        {
            ans*=(sum(factor[i][0],B*factor[i][1])%MOD);
            ans%=MOD;
        }
        printf("%I64d\n",ans);
    }
    return 0;
}
//HDU6069
//大整数约数的个数
//大整数约数个数结论:对于大整数N的因数表达式 N = x1^a1 * x2^a2 ...xn^an
//他的约数的个数是sum = ( 1 + a1 ) *(1 + a2 ) ... ( 1 + an )
//本题还要注意因数分解的方法,认识到给定的数据范围的特殊性,就是对于1e6以外的数,他要么是质数,要么他是1e6以内的质数的幂积和1e6以外的一个质数的幂积,不可能是1e6以外的两个质数的幂积,因为那样一定超过1e12.同时因为L和R的间隔不大于1e6,可以考虑大区间求质数的方法进行因数分解

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
#include<queue>
using namespace std ;

const int maxn = 1e6 +10 ;
const int maxm = 1e6  ;
typedef long long ll ;
const ll mod = 998244353 ;

bool notprime[maxn] ;
ll  prime[maxn] ;

void getprime(){
    memset( notprime , false , sizeof( notprime )) ;
    prime[0] = 0 ;
    for( ll i = 2 ;i<=maxm ;i++){
        if( !notprime[i] )
            prime[ ++ prime[0] ] = i ;
            for( ll j = 2 ; ( ll ) j* i <maxn ; j ++)
                notprime[i * j ] = true ;
    } 
}

ll L , R , K , ans ;
ll dp[maxn] ;
ll sp[maxn] ;

void  solve(){
    ans = 0 ;

    if( L == 1 ){
        ans = 1 ;
        L = 2 ;
    }

    for(ll i = 0 ; i< R-L + 1 ;i++){
        dp[ i ] = i + L ;
    }
    memset( sp , -1 , sizeof( sp )) ;
    for( ll i = 1 ;i<= prime[0] && prime[i] <= R  ;i++){
        ll s = L / prime[i] + ( L % prime[i] > 0 ) ;
        if(s == 1) s = 2 ;
        for( ll j = s ; ( ll ) j* prime[i] <= R; j++){
            if( ( ll ) j *prime[i] >= L ){
                ll temp = 0 ;
/* ll tp = ( ll ) j* prime[i] ; while( tp % prime[i] == 0 ){ temp ++ ; tp /= prime[i ] ; } */                
                ll pos = ( ll ) j * prime[i] - L ;

                while( dp[pos] % prime[i] == 0 ){
                    temp ++ ;
                    dp[pos] /= prime[i] ;
                }

                if( sp[pos] == -1){
                    sp[pos] = ( temp* K  + 1) % mod  ;
                }
                else{
                    sp[pos] = ( sp[pos] * ( ( temp * K + 1) % mod ) ) % mod ;
                }

// cout<<pos + L <<" "<<sp[pos]<<" ====="<<endl;
            }
        }
    }
}

int main(){
    getprime() ;
    int a ;
    scanf("%d" , & a) ;
    while(a --){
        scanf("%lld%lld%lld" , & L, & R , & K) ;
        solve() ;
        for(ll i = 0 ;i< R - L + 1; i++){
            if( sp[i]== -1  )
                ans = ( ans + K + 1 ) % mod ;
            else {
                if( dp[i] == 1)
                    ans = ( ans + sp[i] ) % mod  ; 
                else
                    ans = ( ans + sp[i] * ( K + 1) % mod ) % mod ;
            }
        }        

        printf("%lld\n" , ans % mod);
    }
    return 0 ;
}
    原文作者:大整数乘法问题
    原文地址: https://blog.csdn.net/qq_33785671/article/details/76864251
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞