HDU1452 Happy 2004

题目信息

题目大意是让你求2004的X次方的所有因子之和。

很明显遇到所谓的求什么因子啦,倍数啥的一般都是用数论问题解决。

一个数的因子和是一个积性函数

关于积性函数,即F(ab)=F(a)*F(b),在数论里有很多积性函数

来证明一下:

S(x)表示x的因子和。

如果x可以分成a,b(一定为素数),那么S(x)=S(a)*S(b)。

为什么一定要分成素数呢,因为一个素数的因子之后1和它本身,对于a,b 来说,就是1,a,1,b,那么x=a*b,x的因子只有1,a,,b,x这四个数,

(1+a)*(1+b)=1+a+b+a*b。看明白了么,这就是所谓的一个数的因子和是一个积性函数。

则题目求为:S(2004^X)mod 29

那么可以知道:2004=4 * 3 *167
S(2004^X)=S(2^(2X)) * S(3^X) * S(167^X)

如果 p 是素数 则其因子只有1和它本身,S(p^X)=1+p+p^2+...+p^X = (p^(X+1)-1)/(p-1)

所以:S(2004^X)=(2^(2X+1)-1) * (3^(X+1)-1)/2 * (167^(X+1)-1)/166
考虑到 167%29 == 22
原式可写为     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)
其中inv(c)即满足 (c*inv(c))%M=1的最小整数,用术语讲,inv(c)表示c在模p下的乘法逆元

这里M=29      则inv(1)=1,inv(2)=15,inv(22)=15

原式可写为: S(2004^X)=(2^(2X+1)-1) * (3^(X+1)-1)/2 * (22^(X+1)-1)/21
=(2^(2X+1)-1) * (3^(X+1)-1)*15 * (22^(X+1)-1)*18

进一步15*18%29=9;

所以就是求    :     (2^(2X+1)-1) * (3^(X+1)-1)* (22^(X+1)-1)*9%29;

代码:

#include<cstdio>
#include<iostream>
using namespace std;
int power(int a,int b,int c) { //a的b次方对c取模
	int res=1;
	while(b) {
		if(b&1)
			res=res*a%c;
		a=a*a%c;
		b>>=1;
	}
	--res;
	return res<0?res+c:res;
}

int main()
{
	int x,a,b;
	while(cin>>x&&x)
	{
		a=(2*x+1)%28;
		b=(x+1)%28;
		cout<<9*power(2,a,29)*power(3,b,29)*power(22,b,29)%29<<endl;
	}
 } 

猜你喜欢

转载自blog.csdn.net/qq_39564498/article/details/81324917