zoukankan      html  css  js  c++  java
  • Sumdiv(较难数学题)

    Time Limit: 1000MS   Memory Limit: 30000K
    Total Submissions: 20971   Accepted: 5290

    Description

    Consider two natural numbers A and B. Let S be the sum of all natural divisors of A^B. Determine S modulo 9901 (the rest of the division of S by 9901).

    Input

    The only line contains the two natural numbers A and B, (0 <= A,B <= 50000000)separated by blanks.

    Output

    The only line of the output will contain S modulo 9901.

    Sample Input

    2 3

    Sample Output

    15

    Hint

    2^3 = 8. 
    The natural divisors of 8 are: 1,2,4,8. Their sum is 15. 
    15 modulo 9901 is 15 (that should be output). 
     
    //题意:给出 A,B 问 A^B 的所有因数(包括 1 和本身)之和余 9901 的值
    这道题用了很多个数学的方法,一个个讲
    首先,我们要知道怎么分解一个数,所以用到了<唯一分解定理>: 任何大于1的自然数,都可以唯一分解成有限个质数的乘积
    将 A 分解后,将所有质数个数乘 B 就是 A^B 的该质数的个数了.
    代码:
     1 void Zhi()
     2 {
     3     int t = a;
     4     for (int i=2;i*i<=a;i++)
     5     {
     6         if (t%i==0)
     7         {
     8             p[z]=i;
     9             p_n[z]=1;
    10             t/=i;
    11             while (t%i==0)
    12             {
    13                 p_n[z]++;
    14                 t/=i;
    15             }
    16             z++;
    17         }
    18         if (t==1) break;
    19         if (i!=2)
    20             i++;//2.3.5.7.9...
    21     }
    22     if (t!=1)//本身就是质数
    23     {
    24         p[z]=t;
    25         p_n[z]=1;
    26         z++;
    27     }
    28 }
    View Code
     
    为什么要分解呢,因为要求约数和
    <约数和公式>

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

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

    但是,使用这个公式不能用等比求和公式,因为我们要求余,等比数列求和公式求余就错了

    所以用到了二分求等比数列和

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

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

    前提是要用到<同余模公式>

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

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

    还有<快速幂>

    应该不难,看看代码能懂

     1 int Mi(int a, int b)//快速幂
     2 {
     3     int res = 1;
     4     a %= MOD;
     5     while (b)
     6     {
     7         if (b%2==1)
     8             res = (res * a)%MOD;
     9         a = (a * a)%MOD;
    10         b /= 2;
    11     }
    12     return res;
    13 }
    View Code

    好了,递归二分代码

    1 int Erfen(int p , int n)//求 1 + p + p^2 + p^3+ ... +p^n
    2 {
    3     if (n==0) return 1;
    4     if (n%2==1)
    5         return ((Mi(p,n/2+1)+1)  * Erfen(p,n/2))%MOD;
    6     else
    7         return ((1+Mi(p,n/2+1)) * Erfen(p,n/2-1) + Mi(p,n/2))%MOD;
    8 }
    View Code

    上总代码:

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 
     5 using namespace std;
     6 
     7 #define MOD 9901
     8 
     9 int a,b,z;
    10 int p[10000];   //质数
    11 int p_n[10000];//质数个数
    12 
    13 void Zhi()
    14 {
    15     int t = a;
    16     for (int i=2;i*i<=a;i++)
    17     {
    18         if (t%i==0)
    19         {
    20             p[z]=i;
    21             p_n[z]=1;
    22             t/=i;
    23             while (t%i==0)
    24             {
    25                 p_n[z]++;
    26                 t/=i;
    27             }
    28             z++;
    29         }
    30         if (t==1) break;
    31         if (i!=2)
    32             i++;//2.3.5.7.9...
    33     }
    34     if (t!=1)//本身就是质数
    35     {
    36         p[z]=t;
    37         p_n[z]=1;
    38         z++;
    39     }
    40 }
    41 
    42 int Mi(int a, int b)//快速幂
    43 {
    44     int res = 1;
    45     a %= MOD;
    46     while (b)
    47     {
    48         if (b%2==1)
    49             res = (res * a)%MOD;
    50         a = (a * a)%MOD;
    51         b /= 2;
    52     }
    53     return res;
    54 }
    55 
    56 int Erfen(int p , int n)//求 1 + p + p^2 + p^3+ ... +p^n
    57 {
    58     if (n==0) return 1;
    59     if (n%2==1)
    60         return ((Mi(p,n/2+1)+1)  * Erfen(p,n/2))%MOD;
    61     else
    62         return ((1+Mi(p,n/2+1)) * Erfen(p,n/2-1) + Mi(p,n/2))%MOD;
    63 }
    64 
    65 int main()
    66 {
    67     while (scanf("%d%d",&a,&b)!=EOF)
    68     {
    69         z=0;//质数个数
    70         Zhi();
    71 
    72         int ans = 1;
    73         for (int i=0;i<z;i++)
    74         {
    75             ans = (ans * Erfen(p[i],p_n[i]*b))%MOD;
    76         }
    77         printf("%d
    ",ans);
    78     }
    79     return 0;
    80 }
    View Code
  • 相关阅读:
    阿里云SQL Server远程连接配置
    RSA签名验证无法通过,检查以下部分
    windows开机自动登录
    c# 进程调用exe
    JavaScript console控制台调试 post
    Tesseract-OCR 训练教程(二) 合并新的训练文件
    获取手机唯一标识
    sqlserver 日期与字符串之间的转换
    linq根据英文首字母姓名排序
    js调用浏览器下载
  • 原文地址:https://www.cnblogs.com/haoabcd2010/p/6596778.html
Copyright © 2011-2022 走看看