「NOI2016」循环之美

题目链接

「NOI2016」循环之美

做法

设 k k 进制下循环位数为 a a ,则 xka≡x(mod  y) xk^a \equiv x (\mod y) ,即 ka≡1(mod  y) k^a \equiv 1 (\mod y) ,则 gcd⁡(k,y)=1 \gcd(k, y) = 1 。

Ans=∑i=1n∑j=1m[(i,j)=1][(j,k)=1]=∑j=1m[(j,k)=1]∑i=1n[(i,j)=1]=∑j=1m[(j,k)=1]∑i=1n∑d∣(i,j)μ(d)=∑j=1m[(j,k)=1]∑d∣jμ(d)⌊nd⌋=∑d=1min⁡(n,m)μ(d)⌊nd⌋[(d,k)=1]∑j=1⌊md⌋[(j,k)=1]=∑d=1min⁡(n,m)μ(d)⌊nd⌋[(d,k)=1]∑j=1⌊md⌋∑i∣(j,k)μ(i)=∑d=1min⁡(n,m)μ(d)⌊nd⌋[(d,k)=1]∑i∣k⌊mid⌋.f(n)=∑i∣k⌊mi⌋,Ans=∑d=1min⁡(n,m)μ(d)⌊nd⌋[(d,k)=1]f(⌊md⌋) Ans = \sum_{i = 1}^{n}\sum_{j = 1}^{m}[(i, j) = 1][(j, k) = 1]\\\\ = \sum_{j = 1}^{m}[(j, k) = 1]\sum_{i = 1}^{n}[(i, j) = 1]\\\\ = \sum_{j = 1}^{m}[(j, k) = 1]\sum_{i = 1}^{n}\sum_{d | (i, j)}\mu(d)\\\\ = \sum_{j = 1}^{m}[(j, k) = 1]\sum_{d | j}\mu(d)\lfloor \frac{n}{d} \rfloor\\\\ = \sum_{d = 1}^{\min(n, m)}\mu(d)\lfloor\frac{n}{d}\rfloor[(d, k) = 1]\sum_{j = 1}^{\lfloor \frac{m}{d} \rfloor} [(j, k) = 1]\\\\ = \sum_{d = 1}^{\min(n, m)}\mu(d)\lfloor\frac{n}{d}\rfloor[(d, k) = 1]\sum_{j = 1}^{\lfloor \frac{m}{d} \rfloor} \sum_{i | (j, k)} \mu(i)\\\\ = \sum_{d = 1}^{\min(n, m)}\mu(d)\lfloor\frac{n}{d}\rfloor[(d, k) = 1]\sum_{i| k} \lfloor \frac{m}{id} \rfloor .\\\\ f(n) = \sum_{i| k} \lfloor \frac{m}{i} \rfloor ,\\\\ Ans = \sum_{d = 1}^{\min(n, m)}\mu(d)\lfloor\frac{n}{d}\rfloor[(d, k) = 1] f(\lfloor \frac{m}{d} \rfloor) f(n) f(n) 可以枚举 k k 的因数(k k 很小)。

其中 ⌊md⌋ \lfloor\frac{m}{d}\rfloor 和 ⌊nd⌋ \lfloor\frac{n}{d}\rfloor 可以整除分块。

g(n,k)=∑i=1nμ(i)[(i,k)=1]=∑i=1nμ(i)∑j∣(i,k)μ(j)=∑i=1n∑j∣(i,k)μ(i)μ(j)=∑j∣kμ(j)∑i=1⌊nj⌋μ(ij)=∑j∣kμ(j)∑i=1⌊nj⌋μ(ij)[(i,j)=1]=∑j∣kμ2(j)∑i=1⌊nj⌋μ(i)[(i,j)=1]=∑j∣kμ2(j)g(⌊nj⌋,j). g(n, k) = \sum_{i = 1}^{n}\mu(i)[(i, k) = 1]\\\\ = \sum_{i = 1}^{n}\mu(i)\sum_{j | (i, k)}\mu(j)\\\\ = \sum_{i = 1}^{n}\sum_{j | (i, k)}\mu(i)\mu(j)\\\\ = \sum_{j | k}\mu(j)\sum_{i = 1}^{\lfloor\frac{n}{j}\rfloor}\mu(ij)\\\\ = \sum_{j | k}\mu(j)\sum_{i = 1}^{\lfloor\frac{n}{j}\rfloor}\mu(ij)[(i, j) = 1]\\\\ = \sum_{j | k}\mu^2(j)\sum_{i = 1}^{\lfloor\frac{n}{j}\rfloor}\mu(i)[(i, j) = 1]\\\\ = \sum_{j | k}\mu^2(j)g(\lfloor\frac{n}{j}\rfloor, j) .
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)
#define pb push_back
#define mp make_pair
#define fst first
#define snd second
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 5000010;
ll n, m, k, d[N], ans = 0; int ld = 0;
vector<int> fac[2010];
ll mu[N], smu[N]; int p[N], lp = 0; bool pri[N];
map<ll, ll> Smu, F[2010];

template<typename T> void gi(T &x) {
x = 0; register char c = getchar(), pre = 0;
for(; c < '0' || c > '9'; pre = c, c = getchar());
for(; c >= '0' && c <= '9'; c = getchar()) x = x * 10ll + (c ^ 48);
if(pre == '-') x = -x;
}
ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
void Sieve() {
mu[1] = 1;
rep(i, 2, N - 10) {
if(!pri[i]) p[++lp] = i, mu[i] = -1;
for(int j = 1; p[j] * i <= N - 10; ++j) {
pri[p[j] * i] = 1; if(i % p[j] == 0) break;
mu[p[j] * i] = -mu[i];
}
}
rep(i, 1, N - 10) smu[i] = smu[i - 1] + mu[i];
rep(i, 1, k) if(k % i == 0) d[++ld] = i;
rep(i, 1, 2000) rep(j, 1, i) if(i % j == 0) fac[i].pb(j);
}
ll calc(ll x) {
if(x <= N - 10) return smu[x]; if(Smu.count(x)) return Smu[x];
ll sum = 1;
for(ll l = 2, r; l <= x; l = r + 1) r = x / (x / l), sum -= (r - l + 1) * calc(x / l);
return Smu[x] = sum;
}
ll f(ll x, ll y) {
if(x < 2) return x; if(y == 1) return calc(x);
if(F[y].count(x)) return F[y][x];
ll sum = 0;
for(auto v : fac[y]) if(mu[v]) sum += f(x / v, v);
return F[y][x] = sum;
}
int main() {
gi(n), gi(m), gi(k), Sieve();
for(ll l = 1, r, sum; l <= min(n, m); l = r + 1) {
r = min(n / (n / l), m / (m / l)), sum = 0;
rep(j, 1, ld) sum += mu[d[j]] * (m / l / d[j]); sum *= (n / l);
ans += sum * (f(r, k) - f(l - 1, k));
}
printf("%lld\n", ans);
return 0;
}