Title Link: BZOJ-2440
Problem analysis
First of all, by playing the table and other methods can be known, the answer will not exceed 2 * k.
Then we use two points, for a binary value x, to find out how many of the numbers can be sent between [1, X].
How can I ask for it? We use the repulsion principle.
First, the number that cannot be sent (that is, the number that contains the square factor), and then the total amount minus it.
So, there is a number of squared factors (multiples of 2^2 + 3^2 + 5^2 multiple ...)-the number of square factors with two prime numbers ((2 * 3) ^2 multiples + (2 * 5) ^2 multiple + ...)
In this way, Rukiga can be used to find out how many of the numbers have a square factor.
In this way we have a very high degree of complexity, and we happen to have a MO-colorimetric function that can calculate this value directly.
MOU (x) = {
1 (x = 1)
( -1) ^k (x = p1 * P2 * ... * PK)
0 (x% pi^2 = 0)
}
So we can see that the Möbius value of an X is the same as the coefficient of x^2 in the repulsion.
So, Ans = Sigma (mou[i] * x/(I*i)) (1 <= i <= Sqrt (x))
The Möbius function can be obtained by the linear sieve method.
Code
#include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include < Algorithm> #include <cmath>using namespace std;typedef long long ll;const int MAXN = 100000 + 5;int T, N, K, top;i NT MOU[MAXN], Prime[maxn];bool isprime[maxn];void Prepare () {n = 100000;for (int i = 1; I <= n; ++i) Isprime[i] = True;i SPRIME[1] = false; MOU[1] = 1; Top = 0;for (int i = 2; I <= n; ++i) {if (Isprime[i]) {Prime[++top] = i; Mou[i] =-1;} for (int j = 1; J <= Top && i * prime[j] <= n; ++j) {Isprime[i * prime[j]] = false;if (i% prime[j] = 0) {Mou [i * prime[j]] = 0;break;} Mou[i * Prime[j]] =-mou[i];}}} int Calc (int x) {int ret = 0, sqrtx; SQRTX = (int) sqrt ((double) x); for (int i = 1; I <= sqrtx; ++i) ret + mou[i] * x/i/i;return ret;} int main () {scanf ("%d", &t); Prepare (); for (int case = 1; Case <= T; ++case) {scanf ("%d", &k); LL L = 1, r = k << 1, Mid, Ans;while (L <= r) {mid = (L + R) >> 1;if (Calc ((int) mid) >= k) {Ans= Mid;r = mid-1;} else L = mid + 1;} printf ("%d\n", (int) Ans); return 0;}
[Bzoj 2440] [Zhongshan 2011] Total Square Number "two points + Möbius function"