hdu 1452 Happy 2004 膜拜这推导过程

本文介绍了一种快速计算2004的X次方的所有正因数之和并对29取模的方法。利用数学性质简化计算过程,并通过高效的幂次取模算法实现。适用于解决特定的算法竞赛题目。

Happy 2004

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 920    Accepted Submission(s): 648


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

 

Source
 
 1 /*
 2   性质1 :
 3   如果 gcd(a,b)=1 则 S(a*b)= S(a)*S(b)
 4   2004^X=4^X * 3^X *167^X
 5   S(2004^X)=S(2^(2X)) * S(3^X) * S(167^X)
 6   性质2 :如果 p 是素数 则 S(p^X)=1+p+p^2+...+p^X = (p^(X+1)-1)/(p-1)
 7   (2^(2X+1)-1) * (3^(X+1)-1)/2 * (167^(X+1)-1)/166
 8   167%29 = 22
 9   S(2004^X)=(2^(2X+1)-1) * (3^(X+1)-1)/2 * (22^(X+1)-1)/166
10   性质3 :(a*b)/c %M= a%M * b%M * inv(c)
11   其中inv(c)即满足 (c*inv(c))%M=1的最小整数,这里M=29
12   则inv(1)=1,inv(2)=15,inv(21)=18
13   有上得:
14   S(2004^X)=(2^(2X+1)-1) * (3^(X+1)-1)/2 * (22^(X+1)-1)/21
15   =(2^(2X+1)-1) * (3^(X+1)-1)*15 * (22^(X+1)-1)*18
16 */
17 
18 #include<iostream>
19 #include<stdio.h>
20 #include<cstring>
21 #include<cstdlib>
22 using namespace std;
23 typedef __int64 LL;
24 
25 const LL p = 29;
26 
27 LL pow_mod(LL a,LL n)
28 {
29     LL ans=1;
30     while(n)
31     {
32         if(n&1) ans=(ans*a)%p;
33         n=n>>1;
34         a=(a*a)%p;
35     }
36     ans=ans-1;
37     if(ans<0) ans=ans+p;
38     return ans;
39 }
40 void solve(LL x)
41 {
42     LL sum=1;
43     sum=(sum*pow_mod(3,x+1)*15)%p;
44     sum=(sum*pow_mod(2,2*x+1))%p;
45     sum=(sum*pow_mod(22,x+1)*18)%p;
46     printf("%I64d\n",sum);
47 }
48 int main()
49 {
50     LL x;
51     while(scanf("%I64d",&x)>0)
52     {
53         if(x==0)break;
54         solve(x);
55     }
56     return 0;
57 }

 

转载于:https://www.cnblogs.com/tom987690183/p/3724477.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值