Title Link: HDOJ-5212
Problem analysis
The first idea is to consider the contribution of each number to the final answer.
Then we ask for: For each number, how many pairs it has for GCD.
Obviously, for a number x, the two number that is gcd to it must be a multiple of x. If the multiples of X have K in the sequence, then the GCD with a maximum of k^2 logarithm is x.
It is also obvious that for two numbers, if they are multiples of x, then their gcd must also be multiples of x.
So, we find that multiples of X have K in the sequence, then there are k^2 logarithm satisfies two number is a multiple of x, this k^2 logarithmic gcd, either x, or 2x, 3x, 4x ...
Also, a number is a multiple of x, which must be a multiple of x. So a number pair of gcd in multiples of x must be included in this k^2 logarithm.
If we enumerate x from the large to the small, so that the contribution of X is computed, the multiple multiples of x are already exhausted. We use f (x) to denote the number of pairs with X as GCD.
then f (x) = K^2-f (2x)-F (3x)-f (4x) ... f (TX) (TX <= 10000, k = cnt[x])
This enumerates each x and then enumerates multiples of each x, and the complexity is calculated with a harmonic progression, about O (n logn).
Code
#include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath > #include <algorithm> #include <map> #include <set> #include <queue>using namespace std; typedef long Long Ll;typedef unsigned long long ull;typedef double lf;inline int gmin (int a, int b) {return a < b? A: b;} inline int gmax (int a, int b) {return a > b a:b;} Inline LF gmin (lf A, LF b) {return a < b a:b;} Inline LF Gmax (lf A, LF b) {return a > b a:b;} Const LF EPS = 1e-8;inline lf SQR (lf x) {return x * x;} inline int Sgn (LF x) {if (x <-eps) return-1; if (x > Eps) return 1; return 0; }const int MAXN = 10000 + 5, Mod = 10007;int N, Ans, Num, Temp, Sqrtx;int CNT[MAXN], F[MAXN], Pos[maxn];int main () {WHI Le (scanf ("%d", &n)! = EOF) {for (int i = 1; I <= 10000; ++i) cnt[i] = 0; for (int i = 1; I <= n; ++i) {scanf ("%d", &num); SQRTX = (int) sqrt ((LF) Num); for (int j = 1;J <= Sqrtx; ++J) {if (Num% J! = 0) continue;++cnt[j]; if (num/j! = j) ++cnt[num/j]; }} Ans = 0; for (int i = 10000; I >= 1; i) {f[i] = cnt[i] * Cnt[i]% Mod; for (int j = i * 2; J <= 10000; j + = i) f[i] = (F[i]-f[j] + MoD)% MoD; Temp = i * (i-1)% Mod; Ans = (ans + f[i] * Temp% mod)% MoD; } printf ("%d\n", Ans); } return 0;}
[Hdoj 5212] [Bestcoder round#39] Code "0.0"