zoukankan      html  css  js  c++  java
  • POJ 1845 Sumdiv 【逆元】

    题意:求A^B的所有因子之和

    很容易知道,先把分解得到,那么得到,那么

         的所有因子和的表达式如下

        

    第一种做法是分治求等比数列的和

     用递归二分求等比数列1+pi+pi^2+pi^3+...+pi^n:

    (1)若n为奇数,一共有偶数项,则:
          1 + p + p^2 + p^3 +...+ p^n

          = (1+p^(n/2+1)) + p * (1+p^(n/2+1)) +...+ p^(n/2) * (1+p^(n/2+1))
          = (1 + p + p^2 +...+ p^(n/2)) * (1 + p^(n/2+1))

    (2)若n为偶数,一共有奇数项,则:
          1 + p + p^2 + p^3 +...+ p^n

          = (1+p^(n/2+1)) + p * (1+p^(n/2+1)) +...+ p^(n/2-1) * (1+p^(n/2+1)) + p^(n/2)
          = (1 + p + p^2 +...+ p^(n/2-1)) * (1+p^(n/2+1)) + p^(n/2);

    其他用到的知识是素数筛选以及快速幂,本博客都有相应知识或者百度也行

    #include<stdio.h>
    #include<string.h>
    typedef long long ll;
    const int mod=9901;
    const int N=1e5+11;
    int p[N],pr[N],cnt;
    void init(){
        for(int i=2;i<N;i++){
            if(!p[i])    pr[++cnt]=i;
            for(int j=1;j<=cnt&&i*pr[j]<N;j++){
                p[i*pr[j]]=1;
                if(i%pr[j]==0)    break;
            }
        }
    }
    ll pow_m(ll a,ll b,ll m){
        ll ans=1;a%=m;
        while(b){
            if(b&1)
                ans=(ans*a)%m;
            a=(a*a)%m;
            b>>=1;
        }
        return ans;
    }
    ll sum(ll p,ll n){
        if(!n)    return 1;
        if(n&1){
            return (sum(p,n/2)*(1+pow_m(p,n/2+1,mod)))%mod;
        }
        else{
            return (sum(p,n/2-1)*(1+pow_m(p,n/2+1,mod))+pow_m(p,n/2,mod))%mod;
        }
    } 
    int main(){
        ll a,b;
        init();
        while(~scanf("%lld%lld",&a,&b)){
            ll ans=1;
            for(int i=1;i<=cnt&&pr[i]*pr[i]<=a;i++){
                if(a%pr[i]==0){
                    int num=0;
                    while(a%pr[i]==0){
                        num++;
                        a/=pr[i];
                    }
                    ans=(ans*sum(pr[i],num*b))%mod;
                }
            }
            if(a>1){
                ans=(ans*sum(a,b))%mod;
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }

    第二种方法就是用等比数列求和公式,但是要用逆元。用如下公式即可(已知a|b)

                         

    我们来证明它,已知,证明步骤如下

              

    在快速幂时的乘法会爆longlong,所以用快速乘

    #include<stdio.h>
    #include<string.h>
    typedef long long ll;
    const int mod=9901;
    const int N=1e5+11;
    int p[N],pr[N],cnt;
    void init(){
        for(int i=2;i<N;i++){
            if(!p[i])    pr[++cnt]=i;
            for(int j=1;j<=cnt&&i*pr[j]<N;j++){
                p[i*pr[j]]=1;
                if(i%pr[j]==0)    break;
            }
        }
    }
    ll mul(ll a,ll b,ll m){
        ll ans=0;a%=m;
        while(b){
            if(b&1)
                ans=(ans+a)%m;
            a=(a+a)%m;
            b>>=1;
        }
        return ans;
    }
    ll pow_m(ll a,ll b,ll m){
        ll ans=1;a%=m;
        while(b){
            if(b&1)
                ans=mul(ans,a,m);
            a=mul(a,a,m);
            b>>=1;
        }
        return ans;
    }
    int main(){
        ll a,b;
        init();
        while(~scanf("%lld%lld",&a,&b)){
            ll ans=1;
            for(int i=1;i<=cnt&&pr[i]*pr[i]<=a;i++){
                if(a%pr[i]==0){
                    int num=0;
                    while(a%pr[i]==0){
                        num++;
                        a/=pr[i];
                    }
                    ll M=(pr[i]-1)*mod;
                    ans*=(pow_m(pr[i],num*b+1,M)+M-1)/(pr[i]-1);
                    ans%=mod;
                }
            }
            if(a>1){
                ll M=(a-1)*mod;
                ans*=(pow_m(a,b+1,M)+M-1)/(a-1);
                ans%=mod;
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }

     http://blog.csdn.net/lyy289065406/article/details/6648539

    http://blog.csdn.net/acdreamers/article/details/8220787

  • 相关阅读:
    Sea Battle<海战>(思路题)
    Hat's Fibonacci hdu 1250
    Nearest Neighbor Search
    Divisible by Seven CodeForces
    手机自动化测试:appium源码分析之bootstrap六
    手机自动化测试:appium源码分析之bootstrap五
    手机自动化测试:appium源码分析之bootstrap四
    手机自动化测试:appium源码分析之bootstrap三
    手机自动化测试:appium源码分析之bootstrap二
    手机自动化测试:appium源码分析之bootstrap一
  • 原文地址:https://www.cnblogs.com/L-King/p/5723108.html
Copyright © 2011-2022 走看看