所有因数之和 (题目来源:编程爱好者论坛)

来源:互联网 发布:多例模式 java 编辑:程序博客网 时间:2024/04/29 04:42

第一题:
时间限制:1s
输入2个数字n,s。求数字n的所有因数之和除以s的余数。
 

比如输入
6 5 
6
的因数有1,2,3,6,因数之和为12,因为12除以5的余数为

于是输出2
 

假设n,s都不超过5000000

 

分析:

公式:N可分解为a^m*b^n*c^p……

那末N的所有正因数和为

(1+a+a^2+……+a^m)*(1+b+b^2+……+b^n)*(1+c+c^2+……+c^p)……

简略证明如下:由乘法法则可知,上述括号的连乘积为从所有括号中各取一个相乘,这样就可以保证它包含所有因数

稍微举个简单的例子更好理解:216=2^3*3^3 那末216的所有正因数和即为

 

 

(1+2+4+8)*(1+3+9+27)

 

 

详细分析下为什么这里要size >=sqrt(5000000)

如果不筛选到sqrt50000000),那么一旦给出5000000内的大于已经筛选出的素数的幂次。这样就会把这个数当作一个素数,但是事实不是,而是一个比较大的素数的幂次。故至少要筛选到sqrt5000000)。

参考代码:size=sqrt5000000

 

 

 

  1. #include<stdio.h>   
  2.   
  3. #include<math.h>   
  4.   
  5. #include<stdlib.h>   
  6.   
  7. #define size 2300   
  8.   
  9.     
  10.   
  11. int y[size],p[size],tt;   
  12.   
  13.     
  14.   
  15. int prime()//筛选素数   
  16.   
  17. {   
  18.   
  19.      int i,j,k=0;   
  20.   
  21.      for(i=2;i*i<size;i++)   
  22.   
  23.      {   
  24.   
  25.          if(!y[i]){for(j=i*i;j<size;j+=i)y[j]=1;}   
  26.   
  27.      }   
  28.   
  29.      for(i=2;i<size;i++)   
  30.   
  31.      {if(!y[i]){p[k++]=i;}}   
  32.   
  33.      return k;   
  34.   
  35. }   
  36.   
  37.     
  38.   
  39. int SumFactorMod(int n, int s)   
  40.   
  41. {   
  42.   
  43.      int sum=1,k=0,ps=0,tm;   
  44.   
  45.     
  46.   
  47.      while(k<tt&&p[k]<=n)   
  48.   
  49.      {   
  50.   
  51.          tm=0;   
  52.   
  53.             
  54.   
  55.          while(n!=0&&!(n%p[k]))   
  56.   
  57.          {   
  58.   
  59.               n/=p[k];   
  60.   
  61.               ps++;   
  62.   
  63.          }   
  64.   
  65.         
  66.   
  67.          for(int i=0;i<=ps;i++)   
  68.   
  69.          {       
  70.   
  71.             
  72.   
  73.               tm+=(int)pow(p[k],i);}   
  74.   
  75.          sum*=tm;   
  76.   
  77.         
  78.   
  79.          sum=sum%s;   
  80.   
  81.     
  82.   
  83.          k++;ps=0;   
  84.   
  85.     
  86.   
  87.      }   
  88.   
  89.      if(n>1){   
  90.   
  91.             
  92.   
  93.          sum=(sum*(1+n))%s;   
  94.   
  95.      }   
  96.   
  97.     
  98.   
  99.      return sum;   
  100.   
  101.     
  102.   
  103. }   
  104.   
  105.     
  106.   
  107. int main()   
  108.   
  109. {   
  110.   
  111.      int n,s,sum;   
  112.   
  113.      tt=prime();   
  114.   
  115.     
  116.   
  117.      while(scanf("%d%d",&n,&s)!=EOF)   
  118.   
  119.      {   
  120.   
  121.             
  122.   
  123.         
  124.   
  125.          sum=1;   
  126.   
  127.          if(n!=1)   
  128.   
  129.               sum=SumFactorMod(n,s);   
  130.   
  131.          printf("%d/n",sum%s);   
  132.   
  133.      }   
  134.   
  135.      return 0;   
  136.   
  137. }   
  138.   
  139.    

  

 

 

 

第二题:
输入3个数字n, m, s。求数字nm次方的所有因数之和除以m的余数。 
比如输入
6 2 5 
6^2=36 
36
的因数有1,2,3,4,6,9,12,18,36,因数之和为
91 
91
除以5的余数为1,所以输出1

假设n, m, s都不超过5000000 
这里规定这个s一直是9901  这样好做点。
POJ 1845

 

这个题目比上面的稍微复杂点。知道了a=p1^m1*p2^m2……

那么给出了a^b=p1^(m1*b)*p2^(m2*b)……指数都乘以了b就行

那么a^b的所有因数和=(1+p1^1+p1^2+……p1^(m1*b))*(1+p2^2+……p2^(m2*b))*……

一样吧。只是这个数一大项数很多,而且乘的也很多,只要解决加快项数的运算就行了。

还有就是p2^(m2*b)可能超出int 也超出__int64long long 不要怕 这里有个取余嘛

一边算一边取余就是了。

二分法in乘方

如何计算a^n

1)计算a*a*a**a*a*a,需要计算n-1次乘法,时间复杂度O(n)

2)考虑实例a^4,计算b=a*a,再算c=b*b,则c=a^4,但是只用了两次乘法,效率提高。比如a^9=a*(a^4)*(a^4),只需用4次乘法,一般的,a^n时间复杂度为O(logn)

用于快速算出乘数。

项数也可以用同样方法,二分怎么二分呢?是不是一下子看不出来??

式子都是等比数列吧,项数有奇项与偶项,分开考虑就行了。

首先,偶项:

1+p    1+p+p^2+p^3  1+p+p^2+p^3+p^4+p^5 ……

这些都是偶项的。而且都是后者是前者的两倍,二分的模型来了。

X1=1+p

X2=1+p+p^2(1+p)=(1+p)(1+p^2)   X3=1+p+p^2+p^3+p^4+p^5+p^6+p^7=1+p+p^2(1+p)+p^4+p^5+p^6+p^7=(1+p)*(1+p^2)+p^4(1+p)*(1+p^2)=

(1+p)*(1+p^2)*(1+p^4)

所以是:X3=(X2*(1+P^(2^3/2))=(X1*(1+p^(2^2/2))*(1+p^(2^3/2))  也就是((1+exp(p,k/2))*t)

exp(p,k/2)其实就是算出P^(2^3/2) 这样的。

 

现在,奇项:

X1 =1    项数 1

X2=1+p+p^2 =X1+p^(3/2)*(1+p*X1)   项数 1*2+1

X3=1+p+p^2+p^3+p^4+p^5+p^6=1+p+p^2+p^3*(1+p*(1+p+p^2))=X2+p^(7/2)*(1+p*X2)  项数 :(1*2+1*2+1  前面的 蓝色字体的7就是项数   这个对应式子:(t+exp(p,k/2)*(1+p*t))

exp(p,k/2):相当于p^(7/2)

t:就相当于X

 

相当清楚了吧。。。。。。

 

完整参考代码://参考哦,不保证没有BUG ~~

 

  1. /*7100>=sqrt(50000000)*/  
  2.   
  3. #include<stdio.h>   
  4.   
  5. #define size 7100   
  6.   
  7. #define m 9901   
  8.   
  9.     
  10.   
  11. int y[size],p[size],k;   
  12.   
  13.     
  14.   
  15. void prime()   
  16.   
  17. {   
  18.   
  19.      int i,j;   
  20.   
  21.      k=0;   
  22.   
  23.      for(i=2;i*i<size;i++)   
  24.   
  25.      {   
  26.   
  27.          if(!y[i]){   
  28.   
  29.               for(j=i*i;j<size;j+=i)y[j]=1;   
  30.   
  31.          }   
  32.   
  33.      }   
  34.   
  35.      for(i=2;i<size;i++)   
  36.   
  37.          if(!y[i])   
  38.   
  39.               p[k++]=i;   
  40.   
  41. }   
  42.   
  43.     
  44.   
  45. __int64 exp(__int64 a,__int64 b)   
  46.   
  47. {   
  48.   
  49.      if(b==1)   
  50.   
  51.          return a;   
  52.   
  53.     __int64 t =exp(a,b/2);   
  54.   
  55.      if(b&1)   
  56.   
  57.      {   
  58.   
  59.          return (t*t*a)%m;   
  60.   
  61.      }   
  62.   
  63.          return (t*t)%m;   
  64.   
  65. }   
  66.   
  67.     
  68.   
  69. __int64 sum(__int64 p,__int64 k)   
  70.   
  71. {   
  72.   
  73.      if(k==1)   
  74.   
  75.          return 1;   
  76.   
  77.      __int64 t=sum(p,k/2);   
  78.   
  79.      if(k&1)   
  80.   
  81.      {   
  82.   
  83.          return (t+exp(p,k/2)*(1+p*t))%m;   
  84.   
  85.      }   
  86.   
  87.      else  
  88.   
  89.          return ((1+exp(p,k/2))*t)%m;   
  90.   
  91.     
  92.   
  93. }   
  94.   
  95.     
  96.   
  97.     
  98.   
  99. int main()   
  100.   
  101. {   
  102.   
  103.      int a,b,t,cc;   
  104.   
  105.      __int64 s;   
  106.   
  107.      prime();   
  108.   
  109.      cc=k;   
  110.   
  111.      while(scanf("%d%d",&a,&b)!=EOF)   
  112.   
  113.      {   
  114.   
  115.          if(a==1||b==0)   
  116.   
  117.          {    printf("1/n");   
  118.   
  119.               continue;   
  120.   
  121.          }   
  122.   
  123.     
  124.   
  125.          k=t=0;   
  126.   
  127.          s=1;   
  128.   
  129.          while(k<cc&&p[k]<=a)   
  130.   
  131.          {   
  132.   
  133.               t=0;   
  134.   
  135.               while(a%p[k]==0)   
  136.   
  137.               {   
  138.   
  139.                    a/=p[k];   
  140.   
  141.                    t++;   
  142.   
  143.               }   
  144.   
  145.               s=(s*sum(p[k],t*b+1))%m;   
  146.   
  147.                  
  148.   
  149.               k++;   
  150.   
  151.          }   
  152.   
  153.          if(a>1)   
  154.   
  155.          {   
  156.   
  157.               s*=sum(a,b+1);   
  158.   
  159.               s=s%m;   
  160.   
  161.          }   
  162.   
  163.          printf("%d/n",s );   
  164.   
  165.      }   
  166.   
  167.      return 0;   
  168.   
  169. }  

 

 

 

//在 雨中飞燕 那里做了下题目 又有所收获,视乎在统计

a=p1^m1*p2^m2......   里的m1的时候可以优化。可以想起判断是否是素数只要看小于sqrt(n) 

 

题目是这样的:

 

  1. #include<stdio.h>  
  2. #include<string.h>  
  3. #include<math.h>  
  4. #define size 32000   
  5. int y[size]={0},p[size]={0};   
  6. int prime()   
  7. {   
  8.     int i,j,k=0;   
  9.     for(i=2;i*i<size;i++)   
  10.     {   
  11.         if(!y[i])   
  12.         {   
  13.             for(j=i*i;j<size;j+=i)   
  14.                 y[j]=1;   
  15.         }   
  16.     }   
  17.     for(i=2;i<size;i++)   
  18.         if(!y[i])   
  19.             p[k++]=i;   
  20.     return k;   
  21. }   
  22. void yinzi(int n,int k)   
  23. {   
  24.     int i,t,flag=0;   
  25.     float x=sqrt(n);   
  26.     for(i=0;i<k&&n>1&&p[i]<=x;i++)   
  27.     {   
  28.         t=0;   
  29.         while(n!=0&&n%p[i]==0)   
  30.         {   
  31.             n/=p[i];   
  32.             t++;       
  33.         }   
  34.         if(t)   
  35.         {   
  36.             if(flag)   
  37.             {   
  38.                 printf(" * ");   
  39.             }   
  40.             printf("%d",p[i]);   
  41.             if(t>1)   
  42.             {   
  43.                 printf("^%d",t);   
  44.             }   
  45.             x=sqrt(n);   
  46.             flag=1;   
  47.                
  48.         }   
  49.            
  50.     }   
  51.     if(n>1)   
  52.     {   
  53.         if(flag)   
  54.         printf(" * %d",n);   
  55.         else  
  56.         {   
  57.             printf("%d",n);   
  58.         }   
  59.     }   
  60.     printf("/n");   
  61.        
  62. }   
  63. int main()   
  64. {   
  65.     int n;   
  66.     int k = prime();   
  67.     while(scanf("%d",&n)!=EOF)   
  68.     {   
  69.            
  70.         printf("%d = ",n);   
  71.         if(n==1)   
  72.         {   
  73.             printf("1/n");   
  74.             continue;   
  75.         }   
  76.         yinzi(n,k);   
  77.     }   
  78.     return 0;   
  79. }  

输入n(1 <= n <= 1e9),有多组测试数据:
616
27

输出:
616 = 2^3 * 7 * 11
27 = 3^3
(注意输出空格,但行末不要有空格)

难度:for beginner
参考代码:
原创粉丝点击