题意
一个数有一个power数,现在给出一个区间,求这个区间内的数的和。
思路
可以利用前缀和的思想,算出第一个数总共有的和,然后减去第二个数总共的和。
怎么算和呢?
因为pow(n, 1.0 / k),得出的数是n之内有几个数能开k次方。
那么我们可以对n开1次方、2次……直到开出的数<2
但是这里面有不合法的。比如22∗3和43,显然64的值是6,能开3次方的数中4是无效的。
如何除去这种数?
算出每个被开方数i的倍数,如果该数有效(< 60),dp[i] -= dp[j]。
pow精度被卡,学习了用Java二分。
代码
import java.io.BufferedInputStream;import java.math.BigInteger;import java.util.Scanner;import java.math.*;public class Main {static int MAXN = 60;static long Pow(long num, int k) {long l = 1, r = num + 1, mid, ans = 1;while (l < r) {mid = (l + r) / 2;if (BigInteger.valueOf(mid).pow(k).compareTo(BigInteger.valueOf(num)) <= 0) {//System.out.println(mid);l = mid + 1;ans = mid;}else r = mid;}return ans;}static long Sum(long k) {long[] dp = new long[MAXN];for (int i = 1; i < MAXN; i++) dp[i] = 0;for (int i = 1; i < MAXN; i++) {long n = Pow(k, i);if (n < 2) break;dp[i] = n - 1;//System.out.println(n - 1);}for (int i = MAXN - 1; i > 0; i--) {if (i * 2 >= MAXN) continue;for (int j = i * 2; j < MAXN; j += i) dp[i] -= dp[j];}long ans = 0;for (int i = 1; i < MAXN; i++) ans += i * dp[i];//System.out.println(ans);return ans;}public static void main(String[] args) {Scanner in = new Scanner(new BufferedInputStream(System.in));long a, b;while (in.hasNext()) {a = in.nextLong(); b = in.nextLong();if (a + b == 0) break;System.out.println(Sum(b) - Sum(a - 1));}}}
本文介绍了一种计算指定区间内特定数值和的算法。利用前缀和思想结合精确的幂次运算,去除无效项,最终高效求得区间内所有符合要求的数之和。

890

被折叠的 条评论
为什么被折叠?



