题解 P3653 【小清新数学题】
前言:这题题解太少了叭……?窝码风好康窝来写题解!
观察数据范围发现虽然
考虑
也就是说
因为
为什么只会有这三种情况呢?因为
判断
所以只要筛
#include <cstdio>
#include <cmath>
#define it register int
#define ct const int
#define il inline
using namespace std;
typedef long long ll;
#define rll register ll
#define cll const ll
const int N = 1000005;
int p[N], cnt, mu[N], ans;
bool isp[N];
ll l, r, lft[N];
namespace MR {
const int p[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47 };
il ll mul(cll a, cll b, cll p) {return (a * b - (unsigned long long)((long double)a / p * b + 1e-7) * p + p) % p;}
il ll ksm(rll x, rll L, cll p) { rll ans = 1; while (L) L& 1 ? ans = mul(ans, x, p) : 0, x = mul(x, x, p), L >>= 1; return ans; }
il bool isp(cll n) {
for (it i = 0; i < 14; ++i) if (!(n % p[i])) return n == p[i];
rll r = n - 1;it pw = 0;
while (!(r & 1)) r >>= 1, ++pw;
for (it i = 0, j; i < 14; ++i) {
rll x = ksm(p[i], r, n), y;
for (j = 1; j <= pw && x > 1; ++j) {
y = mul(x, x, n);
if (y == 1 && x != n - 1) return 0;
x = y;
}
if (x ! = 1) return 0;
}
return 1;
}
}
il void Pre() {
it i, j, x;
for (i = 2; i < N; ++i) {
if (!isp[i]) p[++cnt] = i;
for (j = 1; (x = p[j] * i) < N && j < = cnt; ++j) {
isp[x] = 1;
if (!(i % p[j])) break;
}
}
}
int main() {
scanf("%lld%lld", &l, &r), Pre(); it i, x, y;
for (i = r - l, x = 0; x <= i; ++x) lft[x] = x + l, mu[x] = 1;
for (i = 1; i <= cnt && p[i] <= r; ++i)
for (rll j = ((l - 1) / p[i] + 1) * p[i]; j <= r; j += p[i]) {
x = j - l, y = 0;
while (!(lft[x] % p[i])) lft[x] /= p[i], ++y;
mu[x] = (y > 1 ? 0 : -mu[x]);
}
for (i = r - l, x = 0; x <= i; ++x)
lft[x] > 1 ? y = (int)sqrt(lft[x]) , mu[x] = (y * y == lft[x] ? 0 : (MR::isp(lft[x]) ? -mu[x] : mu[x])) : 0, ans += mu[x];
printf("%d", ans);
return 0;
}