zoukankan      html  css  js  c++  java
  • POJ 1845

    题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=27048#problem/C

    数学知识:

    参考:http://youyouaoshu.i.sohu.com/blog/view/87628890.htm

    (1)   整数的唯一分解定理:

          任意正整数都有且只有一种方式写出其素因子的乘积表达式。

          A=(p1^k1)*(p2^k2)*(p3^k3)*....*(pn^kn)   【其中p1,p2,p3.....pi均为质数】

    (2)   约数和公式:

    对于已经分解的整数A=(p1^k1)*(p2^k2)*(p3^k3)*....*(pn^kn)

     (S为A的所有因子之和)

    S = (1+p1+p1^2+p1^3+...p1^k1) * (1+p2+p2^2+p2^3+….p2^k2) * (1+p3+ p3^3+…+ p3^k3) * .... * (1+pn+pn^2+pn^3+...pn^kn)

    (3)   同余模公式:

    (a+b)%m=(a%m+b%m)%m

    (a*b)%m=(a%m*b%m)%m

    了解了这些数学公式此题就比较简单了,还有一点需要注意:由于数据的范围很大,因此在求等比数列时要边求边取余,要不然就是用int64都会超。

    解法:

    1.对A进行分解为公式(1)的形式

    2.S=(1+p1+p1^2+p1^3+...p1^B*k1) * (1+p2+p2^2+p2^3+….p2^B*k2) * (1+p3+ p3^3+…+ p3^B*k3) * .... * (1+pn+pn^2+pn^3+...pn^B*kn)

    3.取余(在求S时,边求边取)

    注:

    转自:優YoU  http://user.qzone.qq.com/289065406/blog/1309237394

    用递归二分求等比数列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))

    上式红色加粗的前半部分恰好就是原式的一半,那么只需要不断递归二分求和就可以了,后半部分为幂次式,将在下面第4点讲述计算方法。

     

    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);

       上式红色加粗的前半部分恰好就是原式的一半,依然递归求解

     

    反复平方法计算幂次式p^n

       这是本题关键所在,求n次幂方法的好坏,决定了本题是否TLE

       p=2n=8为例

       常规是通过连乘法求幂,即2^8=2*2*2*2*2*2*2*2

       这样做的要做8次乘法

     

       而反复平方法则不同,

       定义幂sq=1,再检查n是否大于0

    While,循环过程若发现n为奇数,则把此时的p值乘到sq

    {

       n=8>0 ,把p自乘一次, p=p*p=4     n取半 n=4

       n=4>0 ,再把p自乘一次, p=p*p=16   n取半 n=2

    n=2>0 ,再把p自乘一次, p=p*p=256  n取半 n=1sq=sq*p

    n=1>0 ,再把p自乘一次, p=p*p=256^2  n取半 n=0,弹出循环

    }

    sq=256就是所求,显然反复平方法只做了3次乘法

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #define M 9901
     4 #define MAX 10000
     5 using namespace std;
     6 
     7 int A,B,count;
     8 int p[MAX],c[MAX];
     9 
    10 //求解 x^n
    11 __int64 Pow(__int64 x,__int64 n)
    12 {
    13     __int64 ret=1,s=x;
    14     while(1)
    15     {
    16         if(n&1)
    17             ret=(ret%M*s%M)%M;
    18         if(n>>=1)
    19             s=(s%M*s%M)%M;
    20         else
    21             break;
    22     }
    23     return ret;
    24 }
    25 
    26 //求解 1+p+p^2+...+p^n 等比数列的求和
    27 __int64 Sum(__int64 p,__int64 n)
    28 {
    29     if(n==0)
    30         return 1;
    31     if(n&1)
    32         return ((1+Pow(p,n/2+1))%M*Sum(p,n/2)%M)%M;
    33     else
    34         return ((1+Pow(p,n/2+1))%M*Sum(p,(n-1)/2)%M+Pow(p,n/2)%M)%M;
    35 }
    36 
    37 int main()
    38 {
    39     cin>>A>>B;
    40     int i;
    41     //将A分解成唯一p1^a1*p2^a2*...pi^ai...*pn^an
    42     //p[i]记录pi,c[i]记录ai
    43     for( i=2;i*i<=A;i++)
    44     {
    45         if(A%i==0)
    46         {
    47             p[++count]=i;
    48             while(A%i==0)
    49             {
    50                 A/=i;
    51                 c[count]++;
    52             }
    53         }
    54     }
    55     if(A!=1)
    56     {
    57         p[++count]=A;
    58         c[count]=1;
    59     }
    60     //公式:(A*B)%C=((A%C)*(B%C))%C
    61     __int64 res=1;
    62     for(i=1;i<=count;i++)
    63         res=(res%M*Sum(p[i],B*c[i])%M);
    64     //__int64无法用cout输出
    65     printf("%d
    ",res);
    66     return 0;
    67 }
    View Code
  • 相关阅读:
    @override报错
    idea快捷键
    java中getAttribute与getParameter的区别
    localStorage基于浏览器的本地存储
    js画布组件(<canvas></canvas>)
    easyui
    关于Bootstrap
    使用layUI美化的登录功能
    EXT JS
    ★一些文章链接
  • 原文地址:https://www.cnblogs.com/teilawll/p/3221120.html
Copyright © 2011-2022 走看看