Project Euler 48 Self powers( 大数求余 )


题意:

项的自幂级数求和为 11 + 22 + 33 + … + 1010 = 10405071317。

求如下一千项的自幂级数求和的最后10位数字:11 + 22 + 33 + … + 10001000

思路:

  1. 求最后十位数字 % 1010 即可。

  2. 对于快速幂中数据溢出的问题,有两种解决方法:

    1. 方法一:对于两个数 x y,现在想求 x * y % MOD,可以将 x 表示成 a * DIGS + b,y 表示成 c * DIGS + d,x * y % MOD 则等价与 ( a * c * DIGS2 + a * d * DIGS + b * c * DIGS + b * d ) % MOD ( DIGS = 1E5 ) 这样进行分解后就可以有效的避免数据溢出。
    2. 方法二:对于快速幂中的乘法,我们可以写个与快速幂类似的快速乘法,在快速乘法的过程中不断取模来保持数据在范围之内。

  3. 对于 i % 10 == 0 的情况 i i % MOD 一定为 0


方法一代码:

/*************************************************************************
    > File Name: euler048t2.c
    > Author:    WArobot 
    > Blog:      http://www.cnblogs.com/WArobot/ 
    > Created Time: 2017年07月01日 星期六 16时41分22秒
 ************************************************************************/

#include <stdio.h>
#include <inttypes.h>

#define MOD 10000000000
#define MAX_N 1000
#define DIGS 100000

int64_t Multi(int64_t x , int64_t y) {
	int64_t a , b , c , d , ans = 0;
	a = x / DIGS;	b = x % DIGS;
	c = y / DIGS;	d = y % DIGS;
	ans = (ans + ((a * d) % MOD * DIGS) % MOD) % MOD;
	ans = (ans + ((b * c) % MOD * DIGS) % MOD) % MOD;
	ans = (ans +  (b * d) % MOD) % MOD;
	return ans;
}
int64_t quick_pow(int64_t a , int64_t b , int64_t mod) {
	int64_t ret = 1;
	while (b) {
		if (b & 1)	ret = Multi(ret , a);
		a = Multi(a , a);
		b >>= 1;
	}
	return ret;
}
int32_t main() {
	int64_t sum = 0;
	for (int32_t i = 1 ; i <= MAX_N ; i++) {
		if (i % 10 == 0)	continue;
		sum = (sum + quick_pow(i , i , MOD)) % MOD;
	}
	printf("%"PRId64"\n",sum);
	return 0;
}

方法二代码:

/*************************************************************************
    > File Name: euler048.c
    > Author:    WArobot 
    > Blog:      http://www.cnblogs.com/WArobot/ 
    > Created Time: 2017年07月01日 星期六 16时21分58秒
 ************************************************************************/

#include <stdio.h>
#include <inttypes.h>

#define MAX_N 1000
#define MOD 10000000000

int64_t quick_multi(int64_t a , int64_t b , int64_t mod) {
	int64_t ret = 0;
	while (b) {
		if (b & 1)	ret = (ret + a) % mod;
		a = (a << 1) % mod;
		b >>= 1;
	}
	return ret % mod;
}
int64_t quick_power(int64_t a , int64_t b , int64_t mod) {
	int64_t ret = 1;
	while (b) {
		if (b & 1) ret = quick_multi(ret , a , mod);
		a = quick_multi(a , a , mod);
		b >>= 1;
	}
	return ret % mod;
}
int32_t main() {
	int64_t sum = 0;
	for (int32_t i = 1 ; i <= MAX_N ;i++) {
		if (i % 10 == 0)	continue;
		sum = (sum + (quick_power((int64_t)i , (int64_t)i , MOD))) % MOD;
	}
	printf("%"PRId64"\n",sum);
	return 0;
}
posted @ 2017-07-01 17:03  ojnQ  阅读(352)  评论(0编辑  收藏  举报