Question Link
Given an integer N, evaluate Σ f (I, j) (1 <= j <= I <= N ). Where f (I, j) = I * j/gcd (I/K, J/K) (k is the public factor of I and j)
Idea: Based on the question, we can get a recursive formula ans [N] = ans [n-1] + Σ F (n, j) (1 <= j <= N ), if we can pre-process the section Σ F (n, J), we can output the answer in the case of O (n.
For Σ F (n, J), we use AJ (1 <= j <= N) to represent the set of values that can be obtained by gcd (N/K, J/K, then, we can get Σ F (n, j) = (N * 1/A1 + N * 2/A2 +... + N * n/AN) = N * (1/A1 + 2/A2 +... + N/AN). Note that the value in AJ must be a factor of N. So we can enumerate the factors M, 1 m, 2 m... n, which AJ contains the Factor M can be obtained, so sum (m) = (1 m/m) + (2 m/m) +... + (N/m) = (1 + N/m) * (N/m)/2.
So Sigma F (n, j) = Sigma sum (m) (M is a factor of N ).
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;typedef unsigned __int64 ull;const int MAXN = 500000;const ull MOD = (ull)1 << 32;ull ans[MAXN + 5], sum[MAXN + 5];int n;void init() { memset(ans, 0, sizeof(ans)); memset(sum , 0, sizeof(sum)); for (ull i = 1; i <= MAXN; i++) for (ull j = i; j <= MAXN; j += i) sum[j] += (j / i + 1) * (j / i) / 2; for (ull i = 1; i <= MAXN; i++) { ans[i] = ans[i - 1] + sum[i] * i; ans[i] %= MOD; }}int main() { int t = 1, cas; init(); scanf("%d", &cas); while (cas--) { scanf("%d", &n); printf("Case #%d: %I64u\n", t++, ans[n]); } return 0;}