zoukankan      html  css  js  c++  java
  • HDU 1452 (约数和+乘法逆元)

    题目链接http://acm.hdu.edu.cn/showproblem.php?pid=1452

    题目大意:求2004^X所有约数和,结果mod 29。

    解题思路

    ①整数唯一分解定理:

    一个整数A一定能被分成:A=(P1^K1)*(P2^K2)*(P3^K3).....*(Pn^Kn)的形式。其中Pn为素数。

    如2004=(22)*3*167。

    那么2004x=(22x)*(3x)*(167x)。

    ②约数和公式

    对于一个已经被分解的整数A=(P1^K1)*(P2^K2)*(P3^K3).....*(Pn^Kn),

    有约数和S=(1+P12+P13+.....P1k1)*.....(1+Pn2+Pn3+.....Pnkn)。

    (1+P12+P13+.....P1k1)是一个等比数列,化简为(P1k1+1 -1)/(P1-1).

    对于2004^X, 只要求出a=pow(2,2*x+1)-1,b=pow(3,x+1)-1,c=pow(167,x+1)-1即可,使用快速幂计算,注意快速幂模板里要mod。

    关键问题在于ans=(a*b/2*c/166) mod 29的计算问题,因为除法是不能同余计算的,所以要计算2*166关于29的乘法逆元,转化成乘法取模。

    所以ans=(a*b*c*rev) mod 29。

    #include "cstdio"
    #define LL long long
    #define mod 29
    LL ex_gcd(LL a,LL b,LL &x,LL &y)
    {
        if(a==0&&b==0) return -1;
        if(b==0) {x=1;y=0;return a;}
        LL d=ex_gcd(b,a%b,y,x);
        y-=a/b*x;
        return d;
    }
    LL mod_reverse(LL a,LL n)
    {
        LL x,y,d=ex_gcd(a,n,x,y);
        if(d==1) return (x%n+n)%n;
        else return -1;
    }
    LL pow(LL a,LL n)
    {
        LL base=a,ret=1;
        while(n)
        {
            if(n&1) ret=(ret*base)%mod;
            base=(base*base)%mod;
            n>>=1;
        }
        return ret%mod;
    }
    int main()
    {
        LL T,x;
        while(scanf("%I64d",&x)!=EOF&&x)
        {
            LL a=pow(2,2*x+1)-1,b=pow(3,x+1)-1,c=pow(167,x+1)-1,rev=mod_reverse(2*166,mod);
            printf("%I64d
    ",(a*b*c*rev)%mod);
        }
    }
    12170066 2014-11-13 11:02:46 Accepted 1452 0MS 228K 734 B C++ Physcal

     

     

     

  • 相关阅读:
    linux设置开机服务自动启动
    Redis相关指令文档
    Redis配置文件详解
    redis在windows下的安装
    WIN2003+IIS6+FastCGI+PHP5.3的安装配置
    研究生生活点滴一
    数据链路层
    C++中的static成员
    在构造函数中调用构造函数
    Java和C++的不同
  • 原文地址:https://www.cnblogs.com/neopenx/p/4094505.html
Copyright © 2011-2022 走看看