首页 > 代码库 > HDU 1452 Happy 2004(因子和的积性函数)

HDU 1452 Happy 2004(因子和的积性函数)

题目链接

题意 : 给你一个X,让你求出2004的X次方的所有因子之和,然后对29取余。

思路 : 原来这就是积性函数,点这里这里这里,这里讲得很详细。

 

在非数论的领域,积性函数指所有对于任何a,b都有性质f(ab)=f(a)f(b)的函数。  

在数论中的积性函数:对于正整数n的一个算术函数 f(n),若f(1)=1,且当a,b互质时f(ab)=f(a)f(b),在数论上就称它为积性函数。

若对于某积性函数 f(n),就算a, b不互质,也有f(ab)=f(a)f(b),则称它为完全积性的。

s(6)=s(2)*s(3)=3*4=12;

s(20)=s(4)*s(5)=7*6=42;

再看 s(50)= 1+2+5+10+25+50=93=3*31=s(2)*s(25),s(25)=1+5+25=31.

这在数论中叫积性函数,当gcd(a,b)=1 s(a*b)=s(a)*s(b);

如果p是素数 : s(p^n)=1+p+p^2+...+p^n= (p^(n+1)-1) /(p-1)-----其实就是等比数列求和公式 (1)

 

再看本题 :

计算因子和 s(2004^X) mod 29 ,

2004=2^2 *3 *167

2004^X=4^X * 3^X *167^X

s(2004^X) ) = (s(2^2X))) * (s(3^X))) * (s(167^X))) 而 167%29=22

s(2004^X) ) = (s(2^2X))) * (s(3^X))) * (s(22^X)))

a=s(2^2X)=(2^(2X+1)-1) //根据1

b=s(3^X)= (3^(X+1)-1)/2 //根据1

c=s(22^X)= (22^(X+1)-1)/21 //根据1

%运算法则 

1. (a*b) %p= ( a%p) *(b%p) 乘法的

2. (a/b) %p= ( a *b^(-1)%p) 除法的

s(2004^X)=2^(2X+1)-1* (3^(X+1)-1)/2  *(22^(X+1)-1)/21

(a*b)/c %M= a%M* b%M  * inv(c)

c*inv(c)=1 %M    模为1的所有数  invc)为最小可以被c整除的

inv(2)=15,  inv(21)=18    2*15=1 mod 29, 18*21=1 mod 29

s(2004^X)=((2^(2X+1)-1* (3^(X+1)-1)/2  *(22^(X+1)-1)/21mod 29  =((2^(2X+1)-1)* (3^(X+1)-1)*15 *(22^(X+1)-1)*18)mod29

b^(-1) b的逆元素(%p)即上面的inv

2的逆元素是15  ,因为2*15=30 % 29=1 % 29

21的逆元素是18  ,因为21*18=378% 29 =1 % 29

因此

a=powi(2,2*x+1,29)-1% 29;

b=(powi(3,x+1,29)-1)*15 % 29;

c=(powi(22,x+1,29)-1)*18 % 29;

ans=a*b% 29*c % 29;

 

 

 1 //1452
 2 #include <stdio.h>
 3 #include <math.h>
 4 #include <iostream>
 5 
 6 using namespace std ;
 7 
 8 int multimod(int a,int n)//乘方模
 9 {
10     int res = 1 ;
11     while(n)
12     {
13         if(n & 1)
14         {
15             res *= a ;
16             res %= 29 ;
17         }
18         a *= a ;
19         a %= 29 ;
20         n >>= 1 ;
21     }
22     return res ;
23 }
24 int main()
25 {
26     int x ;
27     while(~scanf("%d",&x))
28     {
29         if(x == 0) break ;
30         int a = (multimod(2,2*x+1)-1) ;
31         int b = (multimod(3,x+1)-1)*15 ;
32         int c = (multimod(167,x+1)-1)*18 ;
33         printf("%d\n",(a*b*c)%29) ;
34     }
35     return 0 ;
36 }
View Code