天天看點

HDU 1452 Happy 2004 (因子和)Happy 2004

Happy 2004

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)

Total Submission(s): 1102 Accepted Submission(s): 791

Problem Description Consider a positive integer X,and let S be the sum of all positive integer divisors of 2004^X. Your job is to determine S modulo 29 (the rest of the division of S by 29).

Take X = 1 for an example. The positive integer divisors of 2004^1 are 1, 2, 3, 4, 6, 12, 167, 334, 501, 668, 1002 and 2004. Therefore S = 4704 and S modulo 29 is equal to 6.

Input The input consists of several test cases. Each test case contains a line with the integer X (1 <= X <= 10000000).

A test case of X = 0 indicates the end of input, and should not be processed.

Output For each test case, in a separate line, please output the result of S modulo 29.

Sample Input

1
10000
0
        

Sample Output

6
10
        
簡單的約數求和。
  
  
   2014^x,由素數基本定理,将2014分解,2014=2^2 *  3 * 167,則2014^x=2^(2*x) * 3^x  *   167^x,由約數和公式(後附)得
  
  
   2014^x的約數和為:[2^(2*x+1)-1]/(2-1)  * [3^(x+1)-1]/(3-1)  *  [167^(x+1)-1]/(167-1) = r/332,
  
  
   其中r=[2^(2*x+1)-1] * [3^(x+1)-1] *  [167^(x+1)-1],答案就是(r/332)%29,在取模運算裡,除以一個數等于乘以這個數的逆元。而332關于模29的逆元是9,故答案就是(r*9)% 29.
  
  
   

  
  
   在這裡還學到的知識:費馬小定理,對任意的素數p,任意整數a,有a^(p-1) mod p =1。
  
  
    
  
  
   在本題裡29是素數,那麼對于a=2014就符合費馬小定理,由費馬小定理,a^28 mod 29 =1,
  
  
   則a^x mod 29 = a^(x mod 28) mod 29.   是以在代碼中處理時,先把x對28取餘。
  
  
   

  
  
   補:約數和公式,有素數基本定理,n=p1^a1 * p2^a2 ....... * pk^ak,
  
  
   約數和為:(p1^(a1+1)-1)/(p1-1) * (p2^(a2+1)-1)/(p2-1) .... * (pk^(ak+1)-1)/(pk-1)
  
  
   

  
  
   
          
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
using namespace std;
typedef __int64 ll;

const int MOD=29;

quick_mod(int a,int b){		//a^b%MOD
	int res=1;
	a%=MOD;
	while(b){
		if(b&1) res=(res*a)%MOD;
		b/=2;
		a=(a*a)%MOD;
	}
	return res;
}

int main()
{
	int i,j,n,res,k;
	while(scanf("%d",&n),n){
		int x1,x2,x3;
		x1=(2*n+1)%(MOD-1);
		x1=quick_mod(2,x1)-1;
		x2=x3=(n+1)%(MOD-1);
		x2=quick_mod(3,x2)-1;
		x3=quick_mod(167,x3)-1;
		res=(x1*x2*x3*9)%MOD;
		printf("%d\n",res);
	}
	return 0;
}
           
補充逆元的求法:a*b mod m =1,則稱a為b的逆元,a,b互為逆元,a模m存在逆元的充要條件是:a和m互素。(這有線性同餘方程的知識可證)。 将a*b mod m =1變形:a*b - m*y =1,要求a的逆元的話就是求b,即線性同餘方程的解,對a和m構造同餘方程,然後求解即可。(用到了擴充歐幾裡得算法Exgcd)
void Exgcd(int a,int b,int &d,int &x,int &y){
	if(b==0){
		x=1;y=0;d=a;return ;
	}
	Exgcd(b,a%b,d,y,x);
	y-=(a/b)*x;
}

//求模n意義下a的逆元,如果不存在則傳回-1
int inv(int a,int n){
	int d,x,y;
	Exgcd(a,n,d,x,y);
	return d==1?(x+n)%n:-1;
}
           
是以本題中332在模29意義下的逆元可以通過 inv(332,29)求得。 本題的解法可以推廣到A^x 的約數和對MOD取餘。見POJ1845 http://poj.org/problem?id=1845 其實也簡單,在本題的解法基礎上,隻需要在開始對A進行素數分解一下就好了。