参考:大佬1 大佬2 大佬3 大佬4
P3455 [POI2007]ZAP-Queries
求 解 ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = k ] 求解\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=k] 求解i=1∑nj=1∑m[gcd(i,j)=k]
反 演 过 程 : 反演过程: 反演过程:
∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = k ] \sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=k] i=1∑nj=1∑m[gcd(i,j)=k]
∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ m k ⌋ ε [ g c d ( i , j ) = 1 ] \sum_{i=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\sum_{j=1}^{\left \lfloor \frac{m}{k} \right \rfloor}\varepsilon[gcd(i,j)=1] i=1∑⌊kn⌋j=1∑⌊km⌋ε[gcd(i,j)=1]
枚 举 d : 枚举d: 枚举d:
∑ d = 1 ⌊ m i n ( ⌊ n k ⌋ , ⌊ m k ⌋ ) ⌋ μ ( d ) ⌊ n k d ⌋ ⌊ m k d ⌋ \sum_{d=1}^{\left \lfloor min(\left \lfloor \frac{n}{k} \right \rfloor,\left \lfloor \frac{m}{k} \right \rfloor)\right \rfloor}\mu(d)\left \lfloor \frac{n}{kd} \right \rfloor \left \lfloor \frac{m}{kd} \right \rfloor d=1∑⌊min(⌊kn⌋,⌊km⌋)⌋μ(d)⌊kdn⌋⌊kdm⌋
先 预 处 理 μ , 然 后 整 数 分 块 做 , 复 杂 度 为 O ( n + T n ) \red{先预处理\mu,然后整数分块做,复杂度为O(n + T\sqrt n)} 先预处理μ,然后整数分块做,复杂度为O(n+Tn)
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;
#define INF 0x7f7f7f
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)
// const ll mod = 998244353;
// const int maxn = 1e5 + 10;
// const double eps = 1e-6;
const int N = 5e5 + 10;
int mu[N]; // 莫比乌斯函数
bool is_prime[N];
int prime[N];
int cnt;
ll sum[N]; // 记录莫比乌斯函数前缀和
void Mobi() // 莫比乌斯函数初始化
{
mu[1] = 1;
is_prime[0] = is_prime[1] = true;
for(int i = 2;i < N; i++) {
if (!is_prime[i]) {
mu[i] = -1;
prime[++cnt] = i;
}
for (int j = 1; j <= cnt && i * prime[j] < N; j++) {
is_prime[i * prime[j]] = true;
if (i % prime[j] == 0) {
mu[i * prime[j]] = 0;
break;
}
mu[i * prime[j]] = -mu[i];
}
}
for(int i = 1;i < N; i++) {
sum[i] = sum[i - 1] + mu[i];
}
}
ll k;
ll Ans(ll n, ll m) {
ll ans = 0;
n /= k, m /= k;
int mx = min(n, m);
for(int l = 1, r;l <= mx; l = r + 1) {
r = min(n / (n / l), m / (m / l));
ans += (n / l) * (m / l) * (sum[r] - sum[l - 1]);
}
return ans;
}
void solve() {
Mobi();
int T;
cin >> T;
while(T--) {
ll n, m;
cin >> n >> m >> k;
cout << Ans(n, m) << endl;
}
}
signed main() {
ios_base::sync_with_stdio(false);
//cin.tie(nullptr);
//cout.tie(nullptr);
#ifdef FZT_ACM_LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
signed test_index_for_debug = 1;
char acm_local_for_debug = 0;
do {
if (acm_local_for_debug == '$') exit(0);
if (test_index_for_debug > 20)
throw runtime_error("Check the stdin!!!");
auto start_clock_for_debug = clock();
solve();
auto end_clock_for_debug = clock();
cout << "Test " << test_index_for_debug << " successful" << endl;
cerr << "Test " << test_index_for_debug++ << " Run Time: "
<< double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
cout << "--------------------------------------------------" << endl;
} while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
solve();
#endif
return 0;
}
P2257 YY的GCD
求 解 ∑ p ∈ p r i m e ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = p ] 求解\sum_{p\in prime}\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=p] 求解p∈prime∑i=1∑nj=1∑m[gcd(i,j)=p]
反 演 过 程 和 上 面 几 乎 一 样 , 就 多 了 一 维 p 为 质 数 的 情 况 , 直 接 化 简 为 : 反演过程和上面几乎一样,就多了一维p为质数的情况,直接化简为: 反演过程和上面几乎一样,就多了一维p为质数的情况,直接化简为:
∑ p ∈ p r i m e ∑ d = 1 ⌊ m i n ( ⌊ n p ⌋ , ⌊ m p ⌋ ) ⌋ μ ( d ) ⌊ n p d ⌋ ⌊ m p d ⌋ \sum_{p\in prime}\sum_{d=1}^{\left \lfloor min(\left \lfloor \frac{n}{p} \right \rfloor,\left \lfloor \frac{m}{p} \right \rfloor)\right \rfloor}\mu(d)\left \lfloor \frac{n}{pd} \right \rfloor \left \lfloor \frac{m}{pd} \right \rfloor p∈prime∑d=1∑⌊min(⌊pn⌋,⌊pm⌋)⌋μ(d)⌊pdn⌋⌊pdm⌋
这 里 的 复 杂 度 为 O ( n + T n n ) , 但 明 显 不 够 , 所 以 需 要 继 续 化 简 , 这 里 的 优 化 可 以 用 T 替 换 p d , 则 d = T p , 替 换 后 的 式 子 为 : 这里的复杂度为O(n+T\sqrt n \sqrt n),但明显不够,所以需要继续化简,这里的优化可以用T替换pd,则d=\frac{T}{p},替换后的式子为: 这里的复杂度为O(n+Tnn),但明显不够,所以需要继续化简,这里的优化可以用T替换pd,则d=pT,替换后的式子为:
∑ T = 1 m i n ( n , m ) ) ⌊ n T ⌋ ⌊ m T ⌋ ∑ p ∣ T p ∈ p r i m e μ ( T p ) \sum_{T=1}^{min(n,m)})\left \lfloor \frac{n}{T} \right \rfloor \left \lfloor \frac{m}{T} \right \rfloor\sum_{p|T\;p\in prime}\mu(\frac{T}{p}) T=1∑min(n,m))⌊Tn⌋⌊Tm⌋p∣Tp∈prime∑μ(pT)
令 F ( x ) = ∑ p ∣ x p ∈ p r i m e μ ( x p ) 令\blue{F(x)=\sum_{p|x\;p\in prime}\mu(\frac{x}{p})} 令F(x)=p∣xp∈prime∑μ(px)
得 : 得: 得:
∑ p ∈ p r i m e ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = p ] = ∑ T = 1 m i n ( n , m ) ⌊ n T ⌋ ⌊ m T ⌋ F ( T ) \sum_{p\in prime}\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=p]=\sum_{T=1}^{min(n,m)}\left \lfloor \frac{n}{T} \right \rfloor \left \lfloor \frac{m}{T} \right \rfloor F(T) p∈prime∑i=1∑nj=1∑m[gcd(i,j)=p]=T=1∑min(n,m)⌊Tn⌋⌊Tm⌋F(T)
O ( n ) 处 理 μ , O ( n l o g n ) 处 理 F , O ( n ) 询 问 分 块 , 即 复 杂 度 为 O ( n l o g n + T n ) \red{O(n)处理\mu,O(nlogn)处理F,O(\sqrt n)询问分块,即复杂度为O(nlogn + T\sqrt n)} O(n)处理μ,O(nlogn)处理F,O(n)询问分块,即复杂度为O(nlogn+Tn)
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;
#define INF 0x7f7f7f
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)
// const ll mod = 998244353;
// const int maxn = 1e5 + 10;
// const double eps = 1e-6;
const int N = 1e7 + 10;
int mu[N]; // 莫比乌斯函数
bool is_prime[N];
int prime[N];
int cnt;
ll sum[N]; // 记录莫比乌斯函数前缀和
ll F[N];
void Mobi() // 莫比乌斯函数初始化
{
mu[1] = 1;
is_prime[0] = is_prime[1] = true;
for(int i = 2;i < N; i++) {
if (!is_prime[i]) {
mu[i] = -1;
prime[++cnt] = i;
}
for (int j = 1; j <= cnt && i * prime[j] < N; j++) {
is_prime[i * prime[j]] = true;
if (i % prime[j] == 0) {
mu[i * prime[j]] = 0;
break;
}
mu[i * prime[j]] = -mu[i];
}
}
for(int i = 1;i <= cnt; i++) {
for(int j = 1;j * prime[i] < N; j++) {
F[j * prime[i]] += mu[j];
}
}
for(int i = 1;i < N; i++) {
F[i] += F[i - 1];
}
}
ll k;
ll Ans(ll N, ll M) {
ll ans = 0;
ll n = N, m = M;
int mx = min(n, m);
for (int l = 1, r; l <= mx; l = r + 1) {
r = min(n / (n / l), m / (m / l));
ans += (n / l) * (m / l) * (F[r] - F[l - 1]);
}
return ans;
}
void solve() {
Mobi();
int T;
cin >> T;
while(T--) {
ll n, m;
cin >> n >> m;
cout << Ans(n, m) << endl;
}
}
signed main() {
ios_base::sync_with_stdio(false);
//cin.tie(nullptr);
//cout.tie(nullptr);
#ifdef FZT_ACM_LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
signed test_index_for_debug = 1;
char acm_local_for_debug = 0;
do {
if (acm_local_for_debug == '$') exit(0);
if (test_index_for_debug > 20)
throw runtime_error("Check the stdin!!!");
auto start_clock_for_debug = clock();
solve();
auto end_clock_for_debug = clock();
cout << "Test " << test_index_for_debug << " successful" << endl;
cerr << "Test " << test_index_for_debug++ << " Run Time: "
<< double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
cout << "--------------------------------------------------" << endl;
} while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
solve();
#endif
return 0;
}
P1390 公约数的和
求 解 ∑ i = 1 n ∑ j = i + 1 n g c d ( i , j ) 求解\sum_{i=1}^n\sum_{j=i+1}^ngcd(i,j) 求解i=1∑nj=i+1∑ngcd(i,j)
先 来 看 看 基 本 形 式 : 先来看看基本形式: 先来看看基本形式:
∑ i = 1 n ∑ j = 1 n g c d ( i , j ) \sum_{i=1}^n\sum_{j=1}^ngcd(i,j) i=1∑nj=1∑ngcd(i,j)
则 a n s = C a l c ( n , n ) − n ( n + 1 ) 2 2 , 首 先 减 去 g c d ( i , i ) 的 个 数 n ( n + 1 ) 2 , 然 后 减 去 g c d ( i , j ) = g c d ( j , i ) 的 个 数 , 直 接 除 2 即 可 , 则 : 则\blue{ans=\frac{Calc(n,n)-\frac{n(n+1)}{2}}{2}},首先减去gcd(i,i)的个数\frac{n(n+1)}{2},然后减去gcd(i,j)=gcd(j,i)的个数,直接除2即可,则: 则ans=2Calc(n,n)−2n(n+1),首先减去gcd(i,i)的个数2n(n+1),然后减去gcd(i,j)=gcd(j,i)的个数,直接除2即可,则:
∑ i = 1 n ∑ j = 1 n ∑ k = 1 n k [ g c d ( i , j ) = k ] \sum_{i=1}^n\sum_{j=1}^n\sum_{k=1}^nk[gcd(i,j)=k] i=1∑nj=1∑nk=1∑nk[gcd(i,j)=k]
枚 举 k : 枚举k: 枚举k:
∑ k = 1 n k ∑ i = 1 ⌊ n k ⌋ ∑ j = ⌊ i + 1 k ⌋ ⌊ n k ⌋ [ g c d ( i , j ) = 1 ] \sum_{k=1}^nk\sum_{i=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\sum_{j=\left \lfloor \frac{i+1}{k} \right \rfloor}^{\left \lfloor \frac{n}{k} \right \rfloor}[gcd(i,j)=1] k=1∑nki=1∑⌊kn⌋j=⌊ki+1⌋∑⌊kn⌋[gcd(i,j)=1]
∑ k = 1 n k ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ n k ⌋ ∑ d ∣ i d ∣ j μ ( d ) \sum_{k=1}^nk\sum_{i=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\sum_{j=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\sum_{d|i\;d|j}\mu(d) k=1∑nki=1∑⌊kn⌋j=1∑⌊kn⌋d∣id∣j∑μ(d)
∑ k = 1 n k ∑ d = 1 ⌊ n k ⌋ μ ( d ) ∑ i = 1 ⌊ n k d ⌋ ∑ j = 1 ⌊ n k d ⌋ 1 \sum_{k=1}^nk\sum_{d=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\mu(d)\sum_{i=1}^{\left \lfloor \frac{n}{kd} \right \rfloor}\sum_{j=1}^{\left \lfloor \frac{n}{kd} \right \rfloor}1 k=1∑nkd=1∑⌊kn⌋μ(d)i=1∑⌊kdn⌋j=1∑⌊kdn⌋1
∑ k = 1 n k ∑ d = 1 ⌊ n k ⌋ μ ( d ) ( ⌊ n k d ⌋ ) 2 \sum_{k=1}^nk\sum_{d=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\mu(d)(\left \lfloor \frac{n}{kd} \right \rfloor)^2 k=1∑nkd=1∑⌊kn⌋μ(d)(⌊kdn⌋)2
令 T = k d 并 枚 举 T , 得 : 令\blue{T=kd并枚举T},得: 令T=kd并枚举T,得:
∑ T = 1 n ∑ d ∣ T μ ( d ) T d ( ⌊ n T ⌋ ) 2 \sum_{T=1}^n\sum_{d|T}\mu(d)\frac{T}{d}(\left \lfloor \frac{n}{T} \right \rfloor)^2 T=1∑nd∣T∑μ(d)dT(⌊Tn⌋)2
中 间 部 分 有 ∑ d ∣ T μ ( d ) T d = φ ( T ) , 因 为 φ = μ ∗ i d , 即 得 : 中间部分有\blue{\sum_{d|T}\mu(d)\frac{T}{d}=\varphi (T),因为\varphi =\mu * id},即得: 中间部分有∑d∣Tμ(d)dT=φ(T),因为φ=μ∗id,即得:
∑ T = 1 n φ ( T ) ( ⌊ n T ⌋ ) 2 \sum_{T=1}^n\varphi (T)(\left \lfloor \frac{n}{T} \right \rfloor)^2 T=1∑nφ(T)(⌊Tn⌋)2
则 最 终 答 案 为 : 则最终答案为: 则最终答案为:
a n s = ∑ T = 1 n φ ( T ) ( ⌊ n T ⌋ ) 2 − n ( n + 1 ) 2 2 \red{ans=\frac{\sum_{T=1}^n\varphi (T)(\left \lfloor \frac{n}{T} \right \rfloor)^2-\frac{n(n+1)}{2}}{2}} ans=2∑T=1nφ(T)(⌊Tn⌋)2−2n(n+1)
O ( n ) 预 处 理 φ , n 询 问 分 块 , 总 时 间 复 杂 度 为 O ( n + n ) \red{O(n)预处理\varphi,\sqrt n询问分块,总时间复杂度为O(n+\sqrt n)} O(n)预处理φ,n询问分块,总时间复杂度为O(n+n)
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;
#define INF 0x7f7f7f
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)
// const ll mod = 998244353;
// const ll P = 1e9 + 7;
// const int maxn = 1e5 + 10;
// const double eps = 1e-6;
const int N = 2e6 + 10;
int phi[N];
bool is_prime[N];
int prime[N];
int tot;
ll f[N];
void Euler()
{
phi[1] = 1;
is_prime[1] = true;
for(int i = 2;i < N; i++){
if(!is_prime[i]) {
phi[i] = i - 1;
prime[++tot] = i;
}
for(int j = 1;j <= tot && i * prime[j] < N; j++){
is_prime[i * prime[j]] = true;
if(i % prime[j]) {
phi[i * prime[j]] = phi[i] * (prime[j] - 1);
}
else{
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
}
}
for(int i = 1;i < N; i++) {
f[i] = f[i - 1] + phi[i];
}
}
ll Calc(ll n) {
ll ans = 0;
for(ll l = 1, r;l <= n;l = r + 1) {
r = min(n, n / (n / l));
ans += (f[r] - f[l - 1]) * (n / l) * (n / l);
}
return ans;
}
void solve() {
Euler();
ll n;
cin >> n;
cout << (Calc(n) - n * (n + 1) / 2) / 2 << endl;
}
signed main() {
ios_base::sync_with_stdio(false);
//cin.tie(nullptr);
//cout.tie(nullptr);
#ifdef FZT_ACM_LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
signed test_index_for_debug = 1;
char acm_local_for_debug = 0;
do {
if (acm_local_for_debug == '$') exit(0);
if (test_index_for_debug > 20)
throw runtime_error("Check the stdin!!!");
auto start_clock_for_debug = clock();
solve();
auto end_clock_for_debug = clock();
cout << "Test " << test_index_for_debug << " successful" << endl;
cerr << "Test " << test_index_for_debug++ << " Run Time: "
<< double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
cout << "--------------------------------------------------" << endl;
} while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
solve();
#endif
return 0;
}
P1829 [国家集训队]Crash的数字表格 / JZPTAB
求 解 ∑ i = 1 n ∑ j = 1 m l c m ( i , j ) 求解\sum_{i=1}^n\sum_{j=1}^mlcm (i,j) 求解i=1∑nj=1∑mlcm(i,j)
由 g c d 和 l c m 之 间 的 关 系 得 : 由gcd和lcm之间的关系得: 由gcd和lcm之间的关系得:
∑ i = 1 n ∑ j = 1 m i j g c d ( i , j ) \sum_{i=1}^n\sum_{j=1}^m\frac{ij}{gcd(i,j)} i=1∑nj=1∑mgcd(i,j)ij
∑ k = 1 m i n ( n , m ) ∑ i = 1 n ∑ j = 1 m i j k [ g c d ( i , j ) = k ] \sum_{k=1}^{min(n,m)}\sum_{i=1}^n\sum_{j=1}^m\frac{ij}{k}[gcd(i,j)=k] k=1∑min(n,m)i=1∑nj=1∑mkij[gcd(i,j)=k]
∑ k = 1 m i n ( n , m ) ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ m k ⌋ i j k 2 k [ g c d ( i , j ) = 1 ] \sum_{k=1}^{min(n,m)}\sum_{i=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\sum_{j=1}^{\left \lfloor \frac{m}{k} \right \rfloor}\frac{ijk^2}{k}[gcd(i,j)=1] k=1∑min(n,m)i=1∑⌊kn⌋j=1∑⌊km⌋kijk2[gcd(i,j)=1]
∑ k = 1 m i n ( n , m ) k ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ m k ⌋ i j ∑ d ∣ i d ∣ j μ ( d ) \sum_{k=1}^{min(n,m)}k\sum_{i=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\sum_{j=1}^{\left \lfloor \frac{m}{k} \right \rfloor}ij\sum_{d|i\;d|j}\mu(d) k=1∑min(n,m)ki=1∑⌊kn⌋j=1∑⌊km⌋ijd∣id∣j∑μ(d)
枚 举 d 得 : 枚举d得: 枚举d得:
∑ k = 1 m i n ( n , m ) k ∑ d = 1 m i n ( ⌊ n k ⌋ , ⌊ m k ⌋ ) μ ( d ) ∑ i = 1 ⌊ n k d ⌋ i d ∑ j = 1 ⌊ m k d ⌋ j d \sum_{k=1}^{min(n,m)}k\sum_{d=1}^{min(\left \lfloor \frac{n}{k} \right \rfloor,\left \lfloor \frac{m}{k} \right \rfloor)}\mu(d)\sum_{i=1}^{\left \lfloor \frac{n}{kd} \right \rfloor}id\sum_{j=1}^{\left \lfloor \frac{m}{kd} \right \rfloor}jd k=1∑min(n,m)kd=1∑min(⌊kn⌋,⌊km⌋)μ(d)i=1∑⌊kdn⌋idj=1∑⌊kdm⌋jd
∑ k = 1 m i n ( n , m ) k ∑ d = 1 m i n ( ⌊ n k ⌋ , ⌊ m k ⌋ ) μ ( d ) d 2 ∑ i = 1 ⌊ n k d ⌋ i ∑ j = 1 ⌊ m k d ⌋ j \sum_{k=1}^{min(n,m)}k\sum_{d=1}^{min(\left \lfloor \frac{n}{k} \right \rfloor,\left \lfloor \frac{m}{k} \right \rfloor)}\mu(d)d^2\sum_{i=1}^{\left \lfloor \frac{n}{kd} \right \rfloor}i\sum_{j=1}^{\left \lfloor \frac{m}{kd} \right \rfloor}j k=1∑min(n,m)kd=1∑min(⌊kn⌋,⌊km⌋)μ(d)d2i=1∑⌊kdn⌋ij=1∑⌊kdm⌋j
令 f ( x ) = ∑ i = 1 x i , F ( n , m ) = ∑ d = 1 m i n ( n , m ) μ ( d ) d 2 f ( n d ) f ( m d ) , 得 : 令\blue{f(x)=\sum_{i=1}^{x}i,F(n,m)=\sum_{d=1}^{min(n,m)}\mu(d)d^2f(\frac{n}{d})f(\frac{m}{d})},得: 令f(x)=∑i=1xi,F(n,m)=∑d=1min(n,m)μ(d)d2f(dn)f(dm),得:
∑ k = 1 m i n ( n , m ) k F ( ⌊ n k ⌋ , ⌊ m k ⌋ ) \sum_{k=1}^{min(n,m)}kF(\left \lfloor\frac{n}{k}\right \rfloor,\left \lfloor\frac{m}{k}\right \rfloor) k=1∑min(n,m)kF(⌊kn⌋,⌊km⌋)
O ( n ) 处 理 μ , O ( 1 ) 处 理 f ( 等 差 数 列 , 在 计 算 F 的 过 程 中 直 接 直 接 计 算 ) , O ( n ) 分 块 询 问 F , 答 案 分 块 询 问 O ( n ) , 总 复 杂 度 为 O ( n + n 3 4 ) \red{O(n)处理\mu,O(1)处理f(等差数列,在计算F的过程中直接直接计算),O(\sqrt {\sqrt n})分块询问F,答案分块询问O(\sqrt n),总复杂度为O(n+n^{\frac{3}{4}})} O(n)处理μ,O(1)处理f(等差数列,在计算F的过程中直接直接计算),O(n)分块询问F,答案分块询问O(n),总复杂度为O(n+n43)
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;
#define INF 0x7f7f7f
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)
// const ll mod = 998244353;
// const int maxn = 1e5 + 10;
// const double eps = 1e-6;
const int N = 1e7 + 10;
const ll mod = 20101009;
int mu[N]; // 莫比乌斯函数
bool is_prime[N];
int prime[N];
int cnt;
ll sum[N];
void Mobi() // 莫比乌斯函数初始化
{
mu[1] = 1;
is_prime[0] = is_prime[1] = true;
for(int i = 2;i < N; i++) {
if (!is_prime[i]) {
mu[i] = -1;
prime[++cnt] = i;
}
for (int j = 1; j <= cnt && i * prime[j] < N; j++) {
is_prime[i * prime[j]] = true;
if (i % prime[j] == 0) {
mu[i * prime[j]] = 0;
break;
}
mu[i * prime[j]] = -mu[i];
}
}
for(int i = 1;i < N; i++) {
sum[i] = (sum[i - 1] + mu[i] * i % mod * i % mod) % mod;
}
}
ll Ans(ll n, ll m)
{
ll inv2 = (mod + 1) / 2;
ll ans = 0;
ll p = min(n, m);
for(int k = 1;k <= p; k++) {
int x = n / k, y = m / k, P = min(x, y);
ll Sum = 0;
for(int l = 1, r;l <= P; l = r + 1) {
r = min(x / (x / l), (y / (y / l)));
Sum = (Sum + (sum[r] - sum[l - 1] + mod) % mod * (1 + x / l) % mod * (x / l) % mod * inv2 % mod * (1 + y / l) % mod * (y / l) % mod * inv2 % mod) % mod;
}
ans = (ans + Sum * k % mod) % mod;
}
return ans;
}
void solve() {
Mobi();
ll n, m;
cin >> n >> m;
cout << Ans(n, m) << endl;
}
signed main() {
ios_base::sync_with_stdio(false);
//cin.tie(nullptr);
//cout.tie(nullptr);
#ifdef FZT_ACM_LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
signed test_index_for_debug = 1;
char acm_local_for_debug = 0;
do {
if (acm_local_for_debug == '$') exit(0);
if (test_index_for_debug > 20)
throw runtime_error("Check the stdin!!!");
auto start_clock_for_debug = clock();
solve();
auto end_clock_for_debug = clock();
cout << "Test " << test_index_for_debug << " successful" << endl;
cerr << "Test " << test_index_for_debug++ << " Run Time: "
<< double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
cout << "--------------------------------------------------" << endl;
} while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
solve();
#endif
return 0;
}
P3768 简单的数学题
求 解 ∑ i = 1 n ∑ j = 1 n i j ( g c d ( i , j ) ) m o d p 求解\sum_{i=1}^n\sum_{j=1}^nij(gcd(i,j))\;mod \;p 求解i=1∑nj=1∑nij(gcd(i,j))modp
∑ k = 1 n ∑ i = 1 n ∑ j = 1 n i j k [ g c d ( i , j ) = k ] \sum_{k=1}^n\sum_{i=1}^n\sum_{j=1}^nijk[gcd(i,j)=k] k=1∑ni=1∑nj=1∑nijk[gcd(i,j)=k]
∑ k = 1 n k ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ n k ⌋ i j k 2 [ g c d ( i , j ) = 1 ] \sum_{k=1}^nk\sum_{i=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\sum_{j=1}^{\left \lfloor \frac{n}{k} \right \rfloor}ijk^2[gcd(i,j)=1] k=1∑nki=1∑⌊kn⌋j=1∑⌊kn⌋ijk2[gcd(i,j)=1]
∑ k = 1 n k 3 ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ n k ⌋ i j ∑ d ∣ i d ∣ j μ ( d ) \sum_{k=1}^nk^3\sum_{i=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\sum_{j=1}^{\left \lfloor \frac{n}{k} \right \rfloor}ij\sum_{d|i\;d|j}\mu(d) k=1∑nk3i=1∑⌊kn⌋j=1∑⌊kn⌋ijd∣id∣j∑μ(d)
∑ k = 1 n k 3 ∑ d = 1 ⌊ n k ⌋ μ ( d ) ∑ i = 1 ⌊ n k d ⌋ i d ∑ j = 1 ⌊ n k d ⌋ j d \sum_{k=1}^nk^3\sum_{d=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\mu(d)\sum_{i=1}^{\left \lfloor \frac{n}{kd} \right \rfloor}id\sum_{j=1}^{\left \lfloor \frac{n}{kd} \right \rfloor}jd k=1∑nk3d=1∑⌊kn⌋μ(d)i=1∑⌊kdn⌋idj=1∑⌊kdn⌋jd
∑ k = 1 n k 3 ∑ d = 1 ⌊ n k ⌋ μ ( d ) d 2 ∑ i = 1 ⌊ n k d ⌋ i ∑ j = 1 ⌊ n k d ⌋ j \sum_{k=1}^nk^3\sum_{d=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\mu(d)d^2\sum_{i=1}^{\left \lfloor \frac{n}{kd} \right \rfloor}i\sum_{j=1}^{\left \lfloor \frac{n}{kd} \right \rfloor}j k=1∑nk3d=1∑⌊kn⌋μ(d)d2i=1∑⌊kdn⌋ij=1∑⌊kdn⌋j
令 f ( x ) = ∑ i = 1 x i , 则 式 子 变 为 : 令\blue{f(x)=\sum_{i=1}^xi},则式子变为: 令f(x)=∑i=1xi,则式子变为:
∑ k = 1 n k 3 ∑ d = 1 ⌊ n k ⌋ μ ( d ) d 2 f 2 ( n k d ) \sum_{k=1}^nk^3\sum_{d=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\mu(d)d^2f^2(\frac{n}{kd}) k=1∑nk3d=1∑⌊kn⌋μ(d)d2f2(kdn)
到 这 里 , 时 间 复 杂 度 为 O ( n + n n ) , 我 没 尝 试 过 , 但 是 还 可 以 继 续 化 简 , 化 简 方 法 有 替 换 , 用 T 替 换 k d , 则 : 到这里,时间复杂度为O(n+n\sqrt n),我没尝试过,但是还可以继续化简,化简方法有替换,用T替换kd,则: 到这里,时间复杂度为O(n+nn),我没尝试过,但是还可以继续化简,化简方法有替换,用T替换kd,则:
∑ T = 1 n f 2 ( n T ) T 2 ∑ k ∣ T k ∗ μ ( T k ) \sum_{T=1}^nf^2(\frac{n}{T})T^2\sum_{k|T}k*\mu(\frac{T}{k}) T=1∑nf2(Tn)T2k∣T∑k∗μ(kT)
∑ T = 1 n f 2 ( n T ) T 2 ( i d ∗ μ ) T \sum_{T=1}^nf^2(\frac{n}{T})T^2\red{(id*\mu)T} T=1∑nf2(Tn)T2(id∗μ)T
∑ T = 1 n f 2 ( n T ) T 2 φ ( T ) \sum_{T=1}^nf^2(\frac{n}{T})T^2\red{\varphi (T)} T=1∑nf2(Tn)T2φ(T)
可 以 杜 教 筛 筛 T 2 φ ( T ) 的 前 缀 和 , 因 为 n 最 高 有 1 0 10 , 明 显 数 组 存 不 下 , 所 以 对 于 5 e 6 可 以 用 数 组 直 接 过 度 求 前 缀 和 , 对 于 后 面 就 可 以 用 杜 教 筛 求 前 缀 和 , 然 后 用 m a p 存 下 ( S T L 的 好 处 ) , 过 程 如 下 : \blue{可以杜教筛筛T^2\varphi (T)的前缀和,因为n最高有10^{10},明显数组存不下,所以对于5e6可以用数组直接过度求前缀和,对于后面就可以用杜教筛求前缀和,然后用map存下(STL的好处),过程如下:} 可以杜教筛筛T2φ(T)的前缀和,因为n最高有1010,明显数组存不下,所以对于5e6可以用数组直接过度求前缀和,对于后面就可以用杜教筛求前缀和,然后用map存下(STL的好处),过程如下:
参 考 : 参考: 参考:杜教筛
先 看 杜 教 筛 的 基 本 形 式 ( 与 上 面 无 关 ) : 设 S ( n ) = ∑ i = 1 n f ( i ) , 定 义 一 个 新 函 数 为 g , 则 有 先看杜教筛的基本形式(与上面无关):设S(n)=\sum_{i=1}^{n}f(i),定义一个新函数为g,则有 先看杜教筛的基本形式(与上面无关):设S(n)=∑i=1nf(i),定义一个新函数为g,则有
∑ i = 1 n ( f ∗ g ) i \sum_{i=1}^n(f*g)i i=1∑n(f∗g)i
∑ i = 1 n ∑ x y = i f ( x ) g ( y ) \sum_{i=1}^n\sum_{xy=i}f(x)g(y) i=1∑nxy=i∑f(x)g(y)
∑ y = 1 n g ( y ) ∑ x y ≤ n f ( x ) \sum_{y=1}^ng(y)\sum_{xy\leq n}f(x) y=1∑ng(y)xy≤n∑f(x)
∑ y = 1 n g ( y ) ∑ x = 1 ⌊ n y ⌋ f ( x ) \sum_{y=1}^ng(y)\sum_{x=1}^{\left \lfloor \frac{n}{y} \right \rfloor}f(x) y=1∑ng(y)x=1∑⌊yn⌋f(x)
∑ y = 1 n g ( y ) S ( ⌊ n y ⌋ ) \sum_{y=1}^ng(y)S(\left \lfloor \frac{n}{y} \right \rfloor) y=1∑ng(y)S(⌊yn⌋)
则 有 : 则有: 则有:
∑ i = 1 n ( f ∗ g ) i = g ( 1 ) S ( n ) + ∑ y = 2 n g ( y ) S ( ⌊ n y ⌋ ) \sum_{i=1}^n(f*g)i=g(1)S(n)+\sum_{y=2}^ng(y)S(\left \lfloor \frac{n}{y} \right \rfloor) i=1∑n(f∗g)i=g(1)S(n)+y=2∑ng(y)S(⌊yn⌋)
S ( n ) = ∑ i = 1 n ( f ∗ g ) i − ∑ y = 2 n g ( y ) S ( ⌊ n y ⌋ ) g ( 1 ) \red{S(n)=\frac{\sum_{i=1}^n(f*g)i-\sum_{y=2}^ng(y)S(\left \lfloor \frac{n}{y} \right \rfloor)}{g(1)}} S(n)=g(1)∑i=1n(f∗g)i−∑y=2ng(y)S(⌊yn⌋)
对 于 本 题 , 要 找 到 合 适 的 g 函 数 , 因 为 我 们 求 的 前 缀 和 为 S ( n ) = ∑ i = 1 n i 2 φ ( i ) , f ( i ) = i 2 φ ( i ) , 所 以 设 g ( n ) = n 2 。 对于本题,要找到合适的g函数,因为我们求的前缀和为S(n)=\sum_{i=1}^ni^2\varphi(i),f(i)=i^2\varphi(i),所以设g(n)=n^2。 对于本题,要找到合适的g函数,因为我们求的前缀和为S(n)=∑i=1ni2φ(i),f(i)=i2φ(i),所以设g(n)=n2。
∑ i = 1 n g ( i ) = x ( x + 1 ) ( 2 x + 1 ) 6 \sum_{i=1}^ng(i)=\frac{x(x+1)(2x+1)}{6} ∑i=1ng(i)=6x(x+1)(2x+1)
( f ∗ g ) x = ∑ d ∣ x f ( d ) g ( x d ) = ∑ d ∣ x d 2 φ ( d ) x 2 d 2 = x 2 ∑ d ∣ x φ ( d ) = x 2 i d ( x ) = x 3 (f*g)x=\sum_{d|x}f(d)g(\frac{x}{d})=\sum_{d|x}d^2\varphi(d)\frac{x^2}{d^2}=x^2\sum_{d|x}\varphi(d)=x^2id(x)=x^3 (f∗g)x=∑d∣xf(d)g(dx)=∑d∣xd2φ(d)d2x2=x2∑d∣xφ(d)=x2id(x)=x3
∑ i = 1 n ( f ∗ g ) i = ∑ i = 1 n i 3 = x 2 ( x + 1 ) 2 4 \sum_{i=1}^n(f*g)i=\sum_{i=1}^ni^3=\frac{x^2(x+1)^2}{4} ∑i=1n(f∗g)i=∑i=1ni3=4x2(x+1)2
S ( n ) = n 2 ( n + 1 ) 2 4 − ∑ y = 2 n g ( y ) S ( ⌊ n y ⌋ ) \red{S(n)=\frac{n^2(n+1)^2}{4}-\sum_{y=2}^ng(y)S(\left \lfloor \frac{n}{y} \right \rfloor)} S(n)=4n2(n+1)2−y=2∑ng(y)S(⌊yn⌋)
O ( n 2 3 ) 处 理 T 2 φ ( T ) 的 前 缀 和 , f 可 以 O ( 1 ) 算 出 , O ( n ) 询 问 分 块 , 总 时 间 复 杂 度 为 O ( n 2 3 ) \red{O(n^{\frac{2}{3}})处理T^2\varphi (T)的前缀和,f可以O(1)算出,O(\sqrt n) 询问分块,总时间复杂度为O(n^\frac{2}{3})} O(n32)处理T2φ(T)的前缀和,f可以O(1)算出,O(n)询问分块,总时间复杂度为O(n32)
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;
#define INF 0x7f7f7f
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)
// const ll mod = 998244353;
// const int maxn = 1e5 + 10;
// const double eps = 1e-6;
const int N = 5e6 + 10;
ll n, mod, inv4, inv6;
ll phi[N];
bool is_prime[N];
int prime[N];
int tot;
ll sum[N];
void Get_phi() {
phi[1] = 1;
is_prime[1] = true;
for(int i = 2;i <= N; i++){
if(!is_prime[i]) {
phi[i] = i - 1;
prime[++tot] = i;
}
for(int j = 1;j <= tot && i * prime[j] < N; j++){
is_prime[i * prime[j]] = true;
if(i % prime[j]) {
phi[i * prime[j]] = phi[i] * (prime[j] - 1);
}
else{
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
}
}
for(int i = 1;i < N; i++) {
sum[i] = (sum[i - 1] + (ll)phi[i] * i % mod * i % mod) % mod;
}
}
ll quick_pow(ll a, ll b) {
ll ans = 1;
while(b){
if(b & 1) ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
}
ll sum1(ll x) {
x %= mod; return (1 + x) % mod * x % mod * (1 + x) % mod * x % mod * inv4 % mod;}
ll sum2(ll x) {
x %= mod; return x % mod * (1 + x) % mod * (2 * x + 1) % mod * inv6 % mod;}
map<ll, ll> mp;
ll Calc(ll x) {
if(x < N) return sum[x];
if(mp[x]) return mp[x];
ll num = sum1(x);
for(ll l = 2, r;l <= x;l = r + 1) {
r = x / (x / l);
num = (num - Calc(x / l) % mod * (sum2(r) - sum2(l - 1) + mod) % mod + mod) % mod;
}
return mp[x] = num;
}
ll Ans() {
ll ans = 0;
for(ll l = 1, r;l <= n; l = r + 1) {
r = n / (n / l);
ans = (ans + sum1(n / l) % mod * (Calc(r) - Calc(l - 1) % mod + mod) % mod) % mod;
}
return ans;
}
void solve() {
cin >> mod >> n;
Get_phi();
inv4 = quick_pow(4, mod - 2);
inv6 = quick_pow(6, mod - 2);
cout << Ans() << endl;
}
signed main() {
ios_base::sync_with_stdio(false);
//cin.tie(nullptr);
//cout.tie(nullptr);
#ifdef FZT_ACM_LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
signed test_index_for_debug = 1;
char acm_local_for_debug = 0;
do {
if (acm_local_for_debug == '$') exit(0);
if (test_index_for_debug > 20)
throw runtime_error("Check the stdin!!!");
auto start_clock_for_debug = clock();
solve();
auto end_clock_for_debug = clock();
cout << "Test " << test_index_for_debug << " successful" << endl;
cerr << "Test " << test_index_for_debug++ << " Run Time: "
<< double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
cout << "--------------------------------------------------" << endl;
} while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
solve();
#endif
return 0;
}
P3327 [SDOI2015]约数个数和
求 解 ∑ i = 1 n ∑ j = 1 m d ( i j ) 求解\sum_{i=1}^n\sum_{j=1}^md (ij) 求解i=1∑nj=1∑md(ij)
约 数 的 重 要 性 质 : ( i j ) = ∑ x ∣ i ∑ y ∣ j [ g c d ( x , y ) = 1 ] \red{约数的重要性质:(ij)=\sum_{x|i}\sum_{y|j}[gcd(x,y )=1]} 约数的重要性质:(ij)=x∣i∑y∣j∑[gcd(x,y)=1]
https://www.cnblogs.com/sun123zxy/p/12295533.html
得 : 得: 得:
∑ i = 1 n ∑ j = 1 m ∑ x ∣ i ∑ y ∣ j [ g c d ( x , y ) = 1 ] \sum_{i=1}^n\sum_{j=1}^m\sum_{x|i}\sum_{y|j}[gcd(x,y )=1] i=1∑nj=1∑mx∣i∑y∣j∑[gcd(x,y)=1]
改 变 枚 举 顺 序 , 枚 举 x 和 y : 改变枚举顺序,枚举x和y: 改变枚举顺序,枚举x和y:
∑ x = 1 n ∑ y = 1 m ⌊ n x ⌋ ⌊ n y ⌋ [ g c d ( x , y ) = 1 ] \sum_{x=1}^n\sum_{y=1}^m\left \lfloor \frac{n}{x} \right \rfloor\left \lfloor \frac{n}{y} \right \rfloor[gcd(x,y)=1] x=1∑ny=1∑m⌊xn⌋⌊yn⌋[gcd(x,y)=1]
∑ i = 1 n ∑ j = 1 m ⌊ n i ⌋ ⌊ n j ⌋ [ g c d ( i , j ) = 1 ] \sum_{i=1}^n\sum_{j=1}^m\left \lfloor \frac{n}{i} \right \rfloor\left \lfloor \frac{n}{j} \right \rfloor[gcd(i,j)=1] i=1∑nj=1∑m⌊in⌋⌊jn⌋[gcd(i,j)=1]
后 面 套 用 前 面 得 : 后面套用前面得: 后面套用前面得:
∑ i = 1 n ∑ j = 1 m ⌊ n i ⌋ ⌊ n j ⌋ ∑ d ∣ i d ∣ j μ ( d ) \sum_{i=1}^n\sum_{j=1}^m\left \lfloor \frac{n}{i} \right \rfloor\left \lfloor \frac{n}{j} \right \rfloor\sum_{d|i\;d|j}\mu(d) i=1∑nj=1∑m⌊in⌋⌊jn⌋d∣id∣j∑μ(d)
枚 举 d 得 : 枚举d得: 枚举d得:
∑ d = 1 m i n ( n , m ) μ ( d ) ∑ i = 1 n ∑ j = 1 m ⌊ n i ⌋ ⌊ n j ⌋ [ d ∣ g c d ( i , j ) ] \sum_{d=1}^{min(n,m)}\mu(d)\sum_{i=1}^n\sum_{j=1}^m\left \lfloor \frac{n}{i} \right \rfloor\left \lfloor \frac{n}{j} \right \rfloor[d|gcd(i,j)] d=1∑min(n,m)μ(d)i=1∑nj=1∑m⌊in⌋⌊jn⌋[d∣gcd(i,j)]
由 于 [ d ∣ g c d ( i , j ) ] 成 立 的 条 件 为 d 是 g c d ( i , j ) 的 约 数 , 所 以 可 以 把 枚 举 i , j 变 换 为 枚 举 d i , d j , 从 而 [ 1 ∣ g c d ( i , j ) ] 可 以 省 略 。 得 : 由于[d|gcd(i,j)]成立的条件为d是gcd(i,j)的约数,所以可以把枚举i,j变换为枚举di,dj,从而[1|gcd(i,j)]可以省略。得: 由于[d∣gcd(i,j)]成立的条件为d是gcd(i,j)的约数,所以可以把枚举i,j变换为枚举di,dj,从而[1∣gcd(i,j)]可以省略。得:
∑ d = 1 m i n ( n , m ) μ ( d ) ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ ⌊ n i d ⌋ ⌊ n j d ⌋ \sum_{d=1}^{min(n,m)}\mu(d)\sum_{i=1}^{\left \lfloor \frac{n}{d} \right \rfloor}\sum_{j=1}^{\left \lfloor\frac{m}{d}\right \rfloor}\left \lfloor \frac{n}{id} \right \rfloor\left \lfloor \frac{n}{jd} \right \rfloor d=1∑min(n,m)μ(d)i=1∑⌊dn⌋j=1∑⌊dm⌋⌊idn⌋⌊jdn⌋
∑ d = 1 m i n ( n , m ) μ ( d ) ∑ i = 1 ⌊ n d ⌋ ⌊ n i d ⌋ ∑ j = 1 ⌊ m d ⌋ ⌊ n j d ⌋ \sum_{d=1}^{min(n,m)}\mu(d)\sum_{i=1}^{\left \lfloor \frac{n}{d} \right \rfloor}\left \lfloor \frac{n}{id} \right \rfloor\sum_{j=1}^{\left \lfloor\frac{m}{d}\right \rfloor}\left \lfloor \frac{n}{jd} \right \rfloor d=1∑min(n,m)μ(d)i=1∑⌊dn⌋⌊idn⌋j=1∑⌊dm⌋⌊jdn⌋
令 f ( x ) = ∑ i = 1 x ⌊ x i ⌋ , 则 : 令\blue{f(x)=\sum_{i=1}^x\left \lfloor \frac{x}{i} \right \rfloor},则: 令f(x)=∑i=1x⌊ix⌋,则:
∑ d = 1 m i n ( n , m ) μ ( d ) f ( n d ) f ( m d ) \sum_{d=1}^{min(n,m)}\mu(d)f(\frac{n}{d})f(\frac{m}{d}) d=1∑min(n,m)μ(d)f(dn)f(dm)
O ( n ) 处 理 μ 和 其 前 缀 和 , O ( n n ) 处 理 f , O ( n ) 询 问 分 块 , 总 复 杂 度 为 O ( n n + T n ) \red{O(n)处理\mu和其前缀和,O(n\sqrt n)处理f,O(\sqrt n)询问分块,总复杂度为O(n\sqrt n+T\sqrt n)} O(n)处理μ和其前缀和,O(nn)处理f,O(n)询问分块,总复杂度为O(nn+Tn)
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;
#define INF 0x7f7f7f
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)
// const ll mod = 998244353;
// const int maxn = 1e5 + 10;
// const double eps = 1e-6;
const int N = 5e4 + 10;
ll mu[N]; // 莫比乌斯函数
bool is_prime[N];
int prime[N];
int cnt;
ll f[N];
void Mobi() // 莫比乌斯函数初始化
{
mu[1] = 1;
is_prime[0] = is_prime[1] = true;
for(int i = 2;i < N; i++) {
if (!is_prime[i]) {
mu[i] = -1;
prime[++cnt] = i;
}
for (int j = 1; j <= cnt && i * prime[j] < N; j++) {
is_prime[i * prime[j]] = true;
if (i % prime[j] == 0) {
mu[i * prime[j]] = 0;
break;
}
mu[i * prime[j]] = -mu[i];
}
}
for(int i = 1;i < N; i++) {
mu[i] += mu[i - 1];
}
for(int i = 1;i < N; i++) {
ll ans = 0;
for(int l = 1, r;l <= i; l = r + 1) {
r = i / (i / l);
ans += (r - l + 1) * (i / l);
}
f[i] = ans;
}
}
ll Ans(ll n, ll m)
{
ll ans = 0;
ll k = min(n, m);
for(ll l = 1, r;l <= k; l = r + 1) {
r = min(n / (n / l), m / (m / l));
ans += (mu[r] - mu[l - 1]) * f[m / l] * f[n / l];
}
return ans;
}
void solve() {
int T;
Mobi();
cin >> T;
while(T--) {
ll n, m;
cin >> n >> m;
cout << Ans(n, m) << endl;
}
}
signed main() {
ios_base::sync_with_stdio(false);
//cin.tie(nullptr);
//cout.tie(nullptr);
#ifdef FZT_ACM_LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
signed test_index_for_debug = 1;
char acm_local_for_debug = 0;
do {
if (acm_local_for_debug == '$') exit(0);
if (test_index_for_debug > 20)
throw runtime_error("Check the stdin!!!");
auto start_clock_for_debug = clock();
solve();
auto end_clock_for_debug = clock();
cout << "Test " << test_index_for_debug << " successful" << endl;
cerr << "Test " << test_index_for_debug++ << " Run Time: "
<< double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
cout << "--------------------------------------------------" << endl;
} while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
solve();
#endif
return 0;
}
P3312 [SDOI2014]数表
求 解 ∑ i = 1 n ∑ j = 1 m ∑ d ∣ i d ∣ j d [ ∑ d ∣ i d ∣ j d ≤ a ] 求解\sum_{i=1}^n\sum_{j=1}^m\sum_{d|i\;d|j}d[\sum_{d|i\;d|j}d\leq a] 求解i=1∑nj=1∑md∣id∣j∑d[d∣id∣j∑d≤a]
令 F ( x ) = ∑ i ∣ x i , 则 得 : 令\blue {F(x)=\sum_{i|x}i},则得: 令F(x)=∑i∣xi,则得:
∑ i = 1 n ∑ j = 1 m F ( g c d ( i , j ) ) [ F ( g c d ( i , j ) ) ≤ a ] \sum_{i=1}^n\sum_{j=1}^m F(gcd(i,j))[F(gcd(i,j))\leq a] i=1∑nj=1∑mF(gcd(i,j))[F(gcd(i,j))≤a]
∑ d = 1 m i n ( n , m ) ∑ i = 1 n ∑ j = 1 m F ( d ) [ g c d ( i , j ) = d ] [ F ( d ) ≤ a ] \sum_{d=1}^{min(n,m)}\sum_{i=1}^n\sum_{j=1}^m F(d)[gcd(i,j)=d][F(d)\leq a] d=1∑min(n,m)i=1∑nj=1∑mF(d)[gcd(i,j)=d][F(d)≤a]
∑ d = 1 m i n ( n , m ) F ( d ) [ F ( d ) ≤ a ] ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = d ] \sum_{d=1}^{min(n,m)}F(d)[F(d)\leq a]\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=d] d=1∑min(n,m)F(d)[F(d)≤a]i=1∑nj=1∑m[gcd(i,j)=d]
后 半 部 分 就 套 用 前 面 得 : 后半部分就套用前面得: 后半部分就套用前面得:
∑ d = 1 m i n ( n , m ) F ( d ) [ F ( d ) ≤ a ] ∑ d ′ = 1 m i n ( ⌊ n d ⌋ , ⌊ m d ⌋ ) μ ( d ′ ) ⌊ n d d ′ ⌋ ⌊ m d d ′ ⌋ \sum_{d=1}^{min(n,m)}F(d)[F(d)\leq a]\sum_{d^{'}=1}^{min(\left \lfloor \frac{n}{d} \right \rfloor, \left \lfloor \frac{m}{d} \right \rfloor)}\mu(d^{'})\left \lfloor \frac{n}{dd^{'}} \right \rfloor \left \lfloor \frac{m}{dd^{'}} \right \rfloor d=1∑min(n,m)F(d)[F(d)≤a]d′=1∑min(⌊dn⌋,⌊dm⌋)μ(d′)⌊dd′n⌋⌊dd′m⌋
令 T 替 换 d d ′ 得 : 令T替换dd^{'}得: 令T替换dd′得:
∑ T = 1 m i n ( n , m ) ∑ d ∣ T F ( d ) μ ( T d ) ⌊ n T ⌋ ⌊ m T ⌋ [ F ( d ) ≤ a ] \sum_{T=1}^{min(n,m)}\sum_{d|T}F(d)\mu(\frac{T}{d})\left \lfloor \frac{n}{T} \right \rfloor \left \lfloor \frac{m}{T} \right \rfloor[F(d)\leq a] T=1∑min(n,m)d∣T∑F(d)μ(dT)⌊Tn⌋⌊Tm⌋[F(d)≤a]
∑ T = 1 m i n ( n , m ) ⌊ n T ⌋ ⌊ m T ⌋ ∑ d ∣ T F ( d ) μ ( T d ) [ F ( d ) ≤ a ] \sum_{T=1}^{min(n,m)}\left \lfloor \frac{n}{T} \right \rfloor \left \lfloor \frac{m}{T} \right \rfloor\sum_{d|T}F(d)\mu(\frac{T}{d})[F(d)\leq a] T=1∑min(n,m)⌊Tn⌋⌊Tm⌋d∣T∑F(d)μ(dT)[F(d)≤a]
令 f ( x ) = ∑ d ∣ x F ( d ) μ ( x d ) [ F ( d ) ≤ a ] 得 : 令\blue{f(x)=\sum_{d|x}F(d)\mu(\frac{x}{d})[F(d)\leq a]}得: 令f(x)=∑d∣xF(d)μ(dx)[F(d)≤a]得:
∑ T = 1 m i n ( n , m ) ⌊ n T ⌋ ⌊ m T ⌋ f ( T ) \sum_{T=1}^{min(n,m)}\left \lfloor \frac{n}{T} \right \rfloor \left \lfloor \frac{m}{T} \right \rfloor f(T) T=1∑min(n,m)⌊Tn⌋⌊Tm⌋f(T)
O ( n ) 处 理 μ , O ( n l o g n ) 处 理 F , 对 于 每 次 询 问 的 a 值 可 以 离 线 排 序 , 树 状 数 组 维 护 f , 处 理 时 间 为 O ( n l o g 2 n ) , O ( n l o g n ) 询 问 分 块 , 总 时 间 复 杂 度 为 O ( n l o g 2 n ) + T n l o g n \red{O(n)处理\mu,O(nlogn)处理F,对于每次询问的a值可以离线排序,树状数组维护f,处理时间为O(nlog^{2}n),O(\sqrt n\; logn)询问分块,总时间复杂度为O(nlog^2n)+T\sqrt n\; logn} O(n)处理μ,O(nlogn)处理F,对于每次询问的a值可以离线排序,树状数组维护f,处理时间为O(nlog2n),O(nlogn)询问分块,总时间复杂度为O(nlog2n)+Tnlogn
Code
由于作者离线的数据结构太菜,本题先咕咕咕
P3172 [CQOI2015]选数
求 解 ∑ i = L H ∑ j = L H . . . ∑ x = L H [ g c d ( i , j . . . x ) = k ] 求解\sum_{i=L}^H\sum_{j=L}^H...\sum_{x=L}^H[gcd(i,j...x)=k] 求解i=L∑Hj=L∑H...x=L∑H[gcd(i,j...x)=k]
本 题 求 n 个 数 的 g c d 为 k 的 个 数 , 根 据 上 面 套 路 , 将 H / k , L / k , 这 样 就 只 用 求 n 个 数 的 g c d 为 1 的 个 数 了 , 注 意 : 如 果 L 整 除 k , 则 L = L / k , 否 则 L = L / k + 1 , 就 是 向 上 取 整 , 那 么 有 一 种 办 法 非 常 好 , 就 让 L / k + ( k − 1 k ) , 即 : 本题求n个数的gcd为k的个数,根据上面套路,将H/k,L/k,这样就只用求n个数的gcd为1的个数了,注意:如果L整除k,则L=L/k,否则L=L/k+1,就是向上取整,那么有一种办法非常好,就让\blue{L/k+(\frac{k-1}{k})},即: 本题求n个数的gcd为k的个数,根据上面套路,将H/k,L/k,这样就只用求n个数的gcd为1的个数了,注意:如果L整除k,则L=L/k,否则L=L/k+1,就是向上取整,那么有一种办法非常好,就让L/k+(kk−1),即:
∑ i = ⌊ L − 1 k ⌋ + 1 ⌊ H k ⌋ ∑ j = ⌊ L − 1 k ⌋ + 1 ⌊ H k ⌋ . . . ∑ x = ⌊ L − 1 k ⌋ + 1 ⌊ H k ⌋ [ g c d ( i , j . . . x ) = 1 ] \sum_{i={\left \lfloor \frac{L-1}{k} \right \rfloor+1}}^{\left \lfloor \frac{H}{k}\right \rfloor}\sum_{j={\left \lfloor \frac{L-1}{k} \right \rfloor+1}}^{\left \lfloor \frac{H}{k}\right \rfloor}...\sum_{x={\left \lfloor \frac{L-1}{k} \right \rfloor+1}}^{\left \lfloor \frac{H}{k}\right \rfloor}[gcd(i,j...x)=1] i=⌊kL−1⌋+1∑⌊kH⌋j=⌊kL−1⌋+1∑⌊kH⌋...x=⌊kL−1⌋+1∑⌊kH⌋[gcd(i,j...x)=1]
∑ i = ⌊ L − 1 k ⌋ + 1 ⌊ H k ⌋ ∑ j = ⌊ L − 1 k ⌋ + 1 ⌊ H k ⌋ . . . ∑ x = ⌊ L − 1 k ⌋ + 1 ⌊ H k ⌋ ∑ d ∣ i d ∣ j . . d ∣ x μ ( d ) \sum_{i={\left \lfloor \frac{L-1}{k} \right \rfloor+1}}^{\left \lfloor \frac{H}{k}\right \rfloor}\sum_{j={\left \lfloor \frac{L-1}{k} \right \rfloor+1}}^{\left \lfloor \frac{H}{k}\right \rfloor}...\sum_{x={\left \lfloor \frac{L-1}{k} \right \rfloor+1}}^{\left \lfloor \frac{H}{k}\right \rfloor}\sum_{d|i\;d|j\;..\;d|x}\mu(d) i=⌊kL−1⌋+1∑⌊kH⌋j=⌊kL−1⌋+1∑⌊kH⌋...x=⌊kL−1⌋+1∑⌊kH⌋d∣id∣j..d∣x∑μ(d)
枚 举 d , 令 l = ⌊ L − 1 k ⌋ + 1 , r = ⌊ H k ⌋ : 枚举d,令\blue{l=\left \lfloor \frac{L-1}{k} \right \rfloor+1,r=\left \lfloor \frac{H}{k}\right \rfloor}: 枚举d,令l=⌊kL−1⌋+1,r=⌊kH⌋:
∑ d = 1 r μ ( d ) ∑ i = l r [ d ∣ i ] ∑ j = l r [ d ∣ j ] . . . ∑ x = l r [ d ∣ x ] \sum_{d=1}^r\mu(d)\sum_{i=l}^r[d|i]\sum_{j=l}^r[d|j]...\sum_{x=l}^r[d|x] d=1∑rμ(d)i=l∑r[d∣i]j=l∑r[d∣j]...x=l∑r[d∣x]
只 有 当 i , j . . . x 都 是 d 的 倍 数 的 时 候 , 最 终 答 案 + 1 , 根 据 容 斥 原 理 , 那 么 在 [ l , r ] 中 d 倍 数 有 r d − l − 1 d , 对 于 所 有 的 i , j . . . x , 他 们 当 中 所 有 [ l , r ] 的 d 的 倍 数 的 个 数 有 ( r d − l − 1 d ) n , 即 为 : 只有当i,j...x都是d的倍数的时候,最终答案+1,根据容斥原理,那么在[l,r]中d倍数有\blue{\frac{r}{d}-\frac{l-1}{d}},对于所有的i,j...x,他们当中所有[l,r]的d的倍数的个数有\blue{(\frac{r}{d}-\frac{l-1}{d})^n},即为: 只有当i,j...x都是d的倍数的时候,最终答案+1,根据容斥原理,那么在[l,r]中d倍数有dr−dl−1,对于所有的i,j...x,他们当中所有[l,r]的d的倍数的个数有(dr−dl−1)n,即为:
∑ d = 1 r μ ( d ) ∗ ( r d − l − 1 d ) n \sum_{d=1}^{r}\mu(d)*(\frac{r}{d}-\frac{l-1}{d})^n d=1∑rμ(d)∗(dr−dl−1)n
这 里 的 H 非 常 大 , 如 果 用 线 性 筛 去 处 理 μ , 会 直 接 W a 掉 , 因 为 没 法 处 理 到 1 0 9 次 方 那 么 大 的 前 缀 和 , 数 组 也 开 不 了 那 么 大 。 后 果 : 这里的H非常大,如果用线性筛去处理\mu,会直接Wa掉,因为没法处理到10^9次方那么大的前缀和,数组也开不了那么大。后果: 这里的H非常大,如果用线性筛去处理μ,会直接Wa掉,因为没法处理到109次方那么大的前缀和,数组也开不了那么大。后果:
这 里 的 A C 可 能 就 是 一 小 部 分 的 运 气 罢 了 。 如 果 用 线 性 筛 , R E 的 R E , W A 的 W A , 所 以 推 荐 用 杜 教 筛 取 筛 。 这里的AC可能就是一小部分的运气罢了。如果用线性筛,RE的RE,WA的WA,所以推荐用杜教筛取筛。 这里的AC可能就是一小部分的运气罢了。如果用线性筛,RE的RE,WA的WA,所以推荐用杜教筛取筛。
设 f ( d ) = μ ( d ) , S ( r ) = ∑ d = 1 n f ( d ) , 这 里 的 S 就 是 要 求 的 前 缀 和 。 \blue{设f(d)=\mu(d),S(r)=\sum_{d=1}^nf(d),这里的S就是要求的前缀和。} 设f(d)=μ(d),S(r)=∑d=1nf(d),这里的S就是要求的前缀和。
我 们 选 择 g = I , 则 ∑ i = 1 r ( f ∗ g ) i = ∑ i = 1 r ( μ ∗ I ) i = ∑ i = 1 r ε ( i ) = 1 。 我们选择\blue{g=I},则\sum_{i=1}^r(f*g)i=\sum_{i=1}^r(\mu*I)i=\sum_{i=1}^r\varepsilon (i)=1。 我们选择g=I,则∑i=1r(f∗g)i=∑i=1r(μ∗I)i=∑i=1rε(i)=1。
枚 举 y : 枚举y: 枚举y:
∑ y = 1 r g ( y ) ∑ x = 1 ⌊ r y ⌋ ) f ( x ) \sum_{y=1}^rg(y)\sum_{x=1}^{\left \lfloor \frac{r}{y} \right \rfloor)}f(x) y=1∑rg(y)x=1∑⌊yr⌋)f(x)
∑ y = 1 r g ( y ) S ( ⌊ r y ⌋ ) \sum_{y=1}^rg(y)S(\left \lfloor \frac{r}{y} \right \rfloor) y=1∑rg(y)S(⌊yr⌋)
∑ i = 1 r ( f ∗ g ) i = g ( 1 ) S ( r ) + ∑ y = 2 r g ( y ) S ( ⌊ r y ⌋ ) \sum_{i=1}^r(f*g)i =g(1)S(r)+\sum_{y=2}^rg(y)S(\left \lfloor \frac{r}{y} \right \rfloor) i=1∑r(f∗g)i=g(1)S(r)+y=2∑rg(y)S(⌊yr⌋)
S ( r ) = ∑ i = 1 r ( f ∗ g ) i − ∑ y = 2 r g ( y ) S ( ⌊ r y ⌋ ) g ( 1 ) S(r)=\frac{\sum_{i=1}^r(f*g)i-\sum_{y=2}^rg(y)S(\left \lfloor \frac{r}{y} \right \rfloor)}{g(1)} S(r)=g(1)∑i=1r(f∗g)i−∑y=2rg(y)S(⌊yr⌋)
当 g = I 时 , 即 : 当g=I时,即: 当g=I时,即:
S ( r ) = 1 − ∑ y = 2 r S ( ⌊ r y ⌋ ) \red{S(r)=1-\sum_{y=2}^rS(\left \lfloor \frac{r}{y} \right \rfloor)} S(r)=1−y=2∑rS(⌊yr⌋)
杜 教 筛 的 复 杂 度 为 O ( n 2 3 ) , 比 线 性 筛 还 要 快 一 点 , 总 时 间 复 杂 度 为 O ( n 2 3 ) 。 \red{杜教筛的复杂度为O(n\frac{2}{3}),比线性筛还要快一点,总时间复杂度为O(n^{\frac{2}{3}})。} 杜教筛的复杂度为O(n32),比线性筛还要快一点,总时间复杂度为O(n32)。
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;
#define INF 0x7f7f7f
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)
// const ll mod = 998244353;
// const int maxn = 1e5 + 10;
// const double eps = 1e-6;
const ll mod = 1e9 + 7;
const int N = 1e6 + 10;
int mu[N]; // 莫比乌斯函数
bool is_prime[N];
int prime[N];
int cnt;
ll sum[N];
ll n, L, H, k;
ll quick_pow(ll a, ll b) {
ll ans = 1;
while(b) {
if(b & 1) ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
}
void Mobi() // 莫比乌斯函数初始化
{
mu[1] = 1;
is_prime[0] = is_prime[1] = true;
for(int i = 2;i < N; i++) {
if (!is_prime[i]) {
mu[i] = -1;
prime[++cnt] = i;
}
for (int j = 1; j <= cnt && i * prime[j] < N; j++) {
is_prime[i * prime[j]] = true;
if (i % prime[j] == 0) {
mu[i * prime[j]] = 0;
break;
}
mu[i * prime[j]] = -mu[i];
}
}
for(int i = 1;i < N; i++) {
sum[i] = (sum[i - 1] + mu[i]) % mod;
}
}
map<ll , ll> mp;
ll Calc(ll x) {
if(x < N)
return sum[x];
if(mp[x])
return mp[x];
ll num = 1;
for(int l = 2, r;l <= x; l = r + 1) {
r = x / (x / l);
num = (num - Calc(x / l) * (r - l + 1) % mod + mod) % mod;
}
return mp[x] = num;
}
ll Ans() {
ll ans = 0;
for(ll l = 1, r;l <= H;l = r + 1) {
r = min(H / (H / l), (L / l) ? L / (L / l) : H + 2);
ans = (ans + (Calc(r) - Calc(l - 1) + mod) % mod * quick_pow((H / l) - (L / l), n) % mod + mod) % mod;
}
return (ans + mod) % mod;
}
void solve() {
cin >> n >> k >> L >> H;
L = (L - 1) / k; // 因为后面需要L-1,所以这里干脆就不+1了,但是含义不同
H = H / k;
Mobi();
cout << Ans() << endl;
}
signed main() {
ios_base::sync_with_stdio(false);
//cin.tie(nullptr);
//cout.tie(nullptr);
#ifdef FZT_ACM_LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
signed test_index_for_debug = 1;
char acm_local_for_debug = 0;
do {
if (acm_local_for_debug == '$') exit(0);
if (test_index_for_debug > 20)
throw runtime_error("Check the stdin!!!");
auto start_clock_for_debug = clock();
solve();
auto end_clock_for_debug = clock();
cout << "Test " << test_index_for_debug << " successful" << endl;
cerr << "Test " << test_index_for_debug++ << " Run Time: "
<< double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
cout << "--------------------------------------------------" << endl;
} while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
solve();
#endif
return 0;
}
AT5200 [AGC038C] LCMs
求 解 ∑ i = 1 N ∑ j = 1 N l c m ( A i , A j ) 求解\sum_{i=1}^{N}\sum_{j=1}^Nlcm(A_i,A_j) 求解i=1∑Nj=1∑Nlcm(Ai,Aj)
莫 比 乌 斯 反 演 处 理 的 一 般 都 是 枚 举 变 量 之 间 的 关 系 , 所 以 我 们 要 让 A i 和 A j 变 为 i 和 j 的 形 式 。 莫比乌斯反演处理的一般都是枚举变量之间的关系,所以我们要让A_i和A_j变为i和j的形式。 莫比乌斯反演处理的一般都是枚举变量之间的关系,所以我们要让Ai和Aj变为i和j的形式。
想 要 用 i 和 j 表 示 A i 和 A j 并 且 不 遗 漏 任 何 的 A , 所 以 让 A 等 于 某 个 i , 就 是 让 c n t i = ∑ d = 1 N [ A d = i ] , 统 计 所 有 A 等 于 某 个 i 的 个 数 , 即 c n t i , j 也 同 样 如 此 , 如 下 所 示 : 想要用i和j表示A_i和A_j并且不遗漏任何的A,所以让A等于某个i,就是让cnt_i=\blue{\sum_{d=1}^N[A_d=i]},统计所有A等于某个i的个数,即cnt_i,j也同样如此,如下所示: 想要用i和j表示Ai和Aj并且不遗漏任何的A,所以让A等于某个i,就是让cnti=∑d=1N[Ad=i],统计所有A等于某个i的个数,即cnti,j也同样如此,如下所示:
∑ i = 1 N ∑ j = 1 N c n t i c n t j l c m ( i , j ) \sum_{i=1}^{N}\sum_{j=1}^Ncnt_icnt_jlcm(i,j) i=1∑Nj=1∑Ncnticntjlcm(i,j)
这 样 还 不 够 , 因 为 i 只 能 是 [ 1 , N ] 的 , 当 A i 中 有 些 值 大 于 N 的 话 , 再 枚 举 i 从 [ 1 , N ] 就 会 漏 掉 大 于 N 的 A i 的 情 况 , 所 以 想 要 统 计 所 有 情 况 , 即 让 N = A i 中 最 大 的 数 即 可 , 即 M = max i = 1 N A i 。 这样还不够,因为i只能是[1,N]的,当Ai中有些值大于N的话,再枚举i从[1,N]就会漏掉大于N的Ai的情况,所以想要统计所有情况,即让N=Ai中最大的数即可,即\blue{M=\max_{i=1}^N {
{ A_i }}}。 这样还不够,因为i只能是[1,N]的,当Ai中有些值大于N的话,再枚举i从[1,N]就会漏掉大于N的Ai的情况,所以想要统计所有情况,即让N=Ai中最大的数即可,即M=maxi=1NAi。
所 以 我 们 需 要 反 演 的 式 子 为 : 所以我们需要反演的式子为: 所以我们需要反演的式子为:
∑ i = 1 M ∑ j = 1 M c n t i ⋅ c n t j ⋅ l c m ( i , j ) \sum_{i=1}^{M}\sum_{j=1}^Mcnt_i ⋅cnt_j ⋅lcm(i,j) i=1∑Mj=1∑Mcnti⋅cntj⋅lcm(i,j)
∑ i = 1 M ∑ j = 1 M c n t i ⋅ c n t j ⋅ i j g c d ( i , j ) \sum_{i=1}^{M}\sum_{j=1}^Mcnt_i ⋅cnt_j ⋅\frac{ij}{gcd(i,j)} i=1∑Mj=1∑Mcnti⋅cntj⋅gcd(i,j)ij
∑ k = 1 M ∑ i = 1 M ∑ j = 1 M c n t i ⋅ c n t j ⋅ i j k [ g c d ( i , j ) = k ] \sum_{k=1}^M\sum_{i=1}^{M}\sum_{j=1}^Mcnt_i ⋅cnt_j ⋅\frac{ij}{k[gcd(i,j)=k]} k=1∑Mi=1∑Mj=1∑Mcnti⋅cntj⋅k[gcd(i,j)=k]ij
∑ k = 1 M ∑ i = 1 ⌊ M k ⌋ ∑ j = 1 ⌊ M k ⌋ c n t i k ⋅ c n t j k ⋅ i j k 2 k [ g c d ( i , j ) = 1 ] \sum_{k=1}^M\sum_{i=1}^{\left \lfloor \frac{M}{k} \right \rfloor}\sum_{j=1}^{\left \lfloor \frac{M}{k} \right \rfloor}cnt_{ik} ⋅cnt_{jk} ⋅\frac{ijk^2}{k}[gcd(i,j)=1] k=1∑Mi=1∑⌊kM⌋j=1∑⌊kM⌋cntik⋅cntjk⋅kijk2[gcd(i,j)=1]
∑ k = 1 M k ∑ i = 1 ⌊ M k ⌋ ∑ j = 1 ⌊ M k ⌋ c n t i k ⋅ c n t j k ⋅ i ⋅ j ∑ d ∣ i d ∣ j μ ( d ) \sum_{k=1}^Mk\sum_{i=1}^{\left \lfloor \frac{M}{k} \right \rfloor}\sum_{j=1}^{\left \lfloor \frac{M}{k} \right \rfloor}cnt_{ik} ⋅cnt_{jk} ⋅i ⋅j\sum_{d|i\;d|j}\mu(d) k=1∑Mki=1∑⌊kM⌋j=1∑⌊kM⌋cntik⋅cntjk⋅i⋅jd∣id∣j∑μ(d)
∑ k = 1 M k ∑ d = 1 ⌊ M k ⌋ μ ( d ) ∑ i = 1 ⌊ M k d ⌋ c n t i k d ⋅ i d ∑ j = 1 ⌊ M k d ⌋ c n t j k d ⋅ j d \sum_{k=1}^Mk\sum_{d=1}^{\left \lfloor \frac{M}{k} \right \rfloor}\mu(d)\sum_{i=1}^{\left \lfloor \frac{M}{kd} \right \rfloor}cnt_{ikd} ⋅id\sum_{j=1}^{\left \lfloor \frac{M}{kd} \right \rfloor}cnt_{jkd} ⋅jd k=1∑Mkd=1∑⌊kM⌋μ(d)i=1∑⌊kdM⌋cntikd⋅idj=1∑⌊kdM⌋cntjkd⋅jd
∑ k = 1 M k ∑ d = 1 ⌊ M k ⌋ μ ( d ) d 2 ( ∑ i = 1 ⌊ M k d ⌋ c n t i k d ⋅ i ) 2 \sum_{k=1}^Mk\sum_{d=1}^{\left \lfloor \frac{M}{k} \right \rfloor}\mu(d)d^2(\sum_{i=1}^{\left \lfloor \frac{M}{kd} \right \rfloor}cnt_{ikd} ⋅i)^2 k=1∑Mkd=1∑⌊kM⌋μ(d)d2(i=1∑⌊kdM⌋cntikd⋅i)2
令 T = k d 则 : 令T=kd则: 令T=kd则:
∑ T = 1 M ( ∑ i = 1 ⌊ M T ⌋ c n t i T ⋅ i ) 2 ∑ k ∣ T μ ( k ) k 2 T k \sum_{T=1}^M(\sum_{i=1}^{\left \lfloor \frac{M}{T} \right \rfloor}cnt_{iT} ⋅i)^2\sum_{k|T}\mu(k)k^2\frac{T}{k} T=1∑M(i=1∑⌊TM⌋cntiT⋅i)2k∣T∑μ(k)k2kT
∑ T = 1 M T ( ∑ i = 1 ⌊ M T ⌋ c n t i T ⋅ i ) 2 ∑ k ∣ T μ ( k ) k \sum_{T=1}^MT(\sum_{i=1}^{\left \lfloor \frac{M}{T} \right \rfloor}cnt_{iT} ⋅i)^2\sum_{k|T}\mu(k)k T=1∑MT(i=1∑⌊TM⌋cntiT⋅i)2k∣T∑μ(k)k
令 f ( x ) = ∑ i ∣ x μ ( i ) i , g ( x ) = ∑ i = 1 ⌊ M x ⌋ c n t i x ⋅ i = 1 x ∑ x ∣ t t c n t t , 则 最 后 的 式 子 为 : 令\blue{f(x)=\sum_{i|x}\mu(i)i\;,\;g(x)=\sum_{i=1}^{\left \lfloor \frac{M}{x} \right \rfloor}cnt_{ix} ⋅i=\frac{1}{x}\sum_{x|t}tcnt_t},则最后的式子为: 令f(x)=∑i∣xμ(i)i,g(x)=∑i=1⌊xM⌋cntix⋅i=x1∑x∣ttcntt,则最后的式子为:
∑ T = 1 M T g 2 ( T ) f ( T ) \sum_{T=1}^MTg^2(T)f(T) T=1∑MTg2(T)f(T)
O ( n ) 处 理 A 的 次 数 , O ( n l o g n ) 处 理 f 和 g , 总 时 间 复 杂 度 为 O ( n l o g n ) \red{O(n)处理A的次数,O(nlogn)处理f和g,总时间复杂度为O(nlogn)} O(n)处理A的次数,O(nlogn)处理f和g,总时间复杂度为O(nlogn)
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;
#define INF 0x7f7f7f
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)
// const ll mod = 998244353;
// const int maxn = 1e5 + 10;
// const double eps = 1e-6;
const int N = 5e5 + 10;
int mu[N]; // 莫比乌斯函数
bool is_prime[N];
int prime[N];
int tot;
ll f[N], g[N];
int M, n;
int cnt[N];
void Mobi() // 莫比乌斯函数初始化
{
mu[1] = 1;
is_prime[0] = is_prime[1] = true;
for(int i = 2;i < N; i++) {
if (!is_prime[i]) {
mu[i] = -1;
prime[++tot] = i;
}
for (int j = 1; j <= tot && i * prime[j] < N; j++) {
is_prime[i * prime[j]] = true;
if (i % prime[j] == 0) {
mu[i * prime[j]] = 0;
break;
}
mu[i * prime[j]] = -mu[i];
}
}
for(int i = 1;i <= M; i++) {
for(int x = i;x <= M; x += i) {
f[x] += mu[i] * i;
}
}
for(int x = 1;x <= M; x++) {
for(int t = x;t <= M; t += x) {
g[x] += t * cnt[t];
}
g[x] /= x;
}
}
void solve() {
cin >> n;
M = n;
for(int i = 1;i <= n; i++) {
int x;
cin >> x;
cnt[x]++;
M = max(M, x);
}
Mobi();
ll ans = 0;
for(int i = 1;i <= M; i++) {
ans += i * g[i] * g[i] * f[i];
}
cout << ans << endl;
}
signed main() {
ios_base::sync_with_stdio(false);
//cin.tie(nullptr);
//cout.tie(nullptr);
#ifdef FZT_ACM_LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
signed test_index_for_debug = 1;
char acm_local_for_debug = 0;
do {
if (acm_local_for_debug == '$') exit(0);
if (test_index_for_debug > 20)
throw runtime_error("Check the stdin!!!");
auto start_clock_for_debug = clock();
solve();
auto end_clock_for_debug = clock();
cout << "Test " << test_index_for_debug << " successful" << endl;
cerr << "Test " << test_index_for_debug++ << " Run Time: "
<< double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
cout << "--------------------------------------------------" << endl;
} while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
solve();
#endif
return 0;
}
SP5971 LCMSUM - LCM Sum
求 解 ∑ i = 1 n l c m ( i , n ) 求解\sum_{i=1}^nlcm(i,n) 求解i=1∑nlcm(i,n)
⌊ n k ⌋ \left \lfloor \frac{n}{k} \right \rfloor ⌊kn⌋
∑ i = 1 n i n g c d ( i , n ) \sum_{i=1}^n\frac{in}{gcd(i,n)} i=1∑ngcd(i,n)in
∑ k = 1 n ∑ i = 1 n i n k [ g c d ( i , n ) = k ] \sum_{k=1}^n\sum_{i=1}^n\frac{in}{k[gcd(i,n)=k]} k=1∑ni=1∑nk[gcd(i,n)=k]in
∑ k = 1 n ∑ i = 1 ⌊ n k ⌋ i n [ g c d ( i , n k ) = 1 ] \sum_{k=1}^n\sum_{i=1}^{\left \lfloor \frac{n}{k} \right \rfloor}in[gcd(i,\frac{n}{k})=1] k=1∑ni=1∑⌊kn⌋in[gcd(i,kn)=1]
n ∑ k = 1 n ∑ i = 1 ⌊ n k ⌋ i [ g c d ( i , n k ) = 1 ] n\sum_{k=1}^n\sum_{i=1}^{\left \lfloor \frac{n}{k} \right \rfloor}i[gcd(i,\frac{n}{k})=1] nk=1∑ni=1∑⌊kn⌋i[gcd(i,kn)=1]
n ∑ k ∣ n ∑ i = 1 k i [ g c d ( i , k ) = 1 ] n\sum_{k|n}\sum_{i=1}^ki[gcd(i,k)=1] nk∣n∑i=1∑ki[gcd(i,k)=1]
n ∑ k ∣ n ∑ i = 1 k i ∑ d ∣ i d ∣ k μ ( d ) n\sum_{k|n}\sum_{i=1}^ki\sum_{d|i\;d|k}\mu(d) nk∣n∑i=1∑kid∣id∣k∑μ(d)
枚 举 d : 枚举d: 枚举d:
n ∑ k ∣ n ∑ d ∣ k μ ( d ) ∑ i = 1 ⌊ k d ⌋ i d n\sum_{k|n}\sum_{d|k}\mu(d)\sum_{i=1}^{\left \lfloor \frac{k}{d} \right \rfloor}id nk∣n∑d∣k∑μ(d)i=1∑⌊dk⌋id
n ∑ k ∣ n ∑ d ∣ k μ ( d ) d ∑ i = 1 ⌊ k d ⌋ i n\sum_{k|n}\sum_{d|k}\mu(d)d\sum_{i=1}^{\left \lfloor \frac{k}{d} \right \rfloor}i nk∣n∑d∣k∑μ(d)di=1∑⌊dk⌋i
n ∑ k ∣ n ∑ d ∣ k μ ( d ) d ⌊ k d ⌋ ∗ ( ⌊ k d ⌋ + 1 ) 2 n\sum_{k|n}\sum_{d|k}\mu(d)d\frac{\left \lfloor \frac{k}{d} \right \rfloor*(\left \lfloor \frac{k}{d} \right \rfloor+1)}{2} nk∣n∑d∣k∑μ(d)d2⌊dk⌋∗(⌊dk⌋+1)
n 2 ∑ k ∣ n { ∑ d ∣ k μ ( d ) ∗ k 2 d + ∑ d ∣ k μ ( d ) ∗ k } \frac{n}{2}\sum_{k|n}\{\sum_{d|k}\mu(d)*\frac{k^2}{d}+\sum_{d|k}\mu(d)*k\} 2nk∣n∑{ d∣k∑μ(d)∗dk2+d∣k∑μ(d)∗k}
n 2 ∑ k ∣ n k { ∑ d ∣ k μ ( d ) ∗ k d + ∑ d ∣ k μ ( d ) } \frac{n}{2}\sum_{k|n}k\{\sum_{d|k}\mu(d)*\frac{k}{d}+\sum_{d|k}\mu(d)\} 2nk∣n∑k{ d∣k∑μ(d)∗dk+d∣k∑μ(d)}
这 时 候 发 现 两 个 狄 利 克 雷 卷 积 , φ ( n ) = μ ∗ i d = ∑ d ∣ n μ ( d ) ∗ n d , ε ( n ) = μ ∗ I = ∑ d ∣ n μ ( d ) 。 所 以 我 们 将 其 替 换 得 : \blue{这时候发现两个狄利克雷卷积,\varphi (n)=\mu*id=\sum_{d|n}\mu(d)*\frac{n}{d}\;\;,\;\;\varepsilon(n) =\mu*I=\sum_{d|n}\mu(d)。所以我们将其替换得:} 这时候发现两个狄利克雷卷积,φ(n)=μ∗id=∑d∣nμ(d)∗dn,ε(n)=μ∗I=∑d∣nμ(d)。所以我们将其替换得:
n 2 ∑ k ∣ n k [ φ ( k ) + ε ( k ) ] \frac{n}{2}\sum_{k|n}k[\varphi(k)+\varepsilon(k)] 2nk∣n∑k[φ(k)+ε(k)]
O ( n ) 处 理 φ , n 询 问 答 案 , 总 复 杂 度 为 O ( n + T n ) 。 \red{O(n)处理\varphi,\sqrt n询问答案,总复杂度为O(n+T\sqrt n)。} O(n)处理φ,n询问答案,总复杂度为O(n+Tn)。
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;
#define INF 0x7f7f7f
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)
// const ll mod = 998244353;
// const int maxn = 1e5 + 10;
// const double eps = 1e-6;
const int N = 1e6 + 10;
int phi[N];
bool is_prime[N];
int prime[N];
int tot;
ll f[N];
void Euler()
{
phi[1] = 1;
is_prime[1] = true;
for(int i = 2;i < N; i++){
if(!is_prime[i]) {
phi[i] = i - 1;
prime[++tot] = i;
}
for(int j = 1;j <= tot && i * prime[j] < N; j++){
is_prime[i * prime[j]] = true;
if(i % prime[j]) {
phi[i * prime[j]] = phi[i] * (prime[j] - 1);
}
else{
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
}
}
for(int i = 1;i < N; i++) {
for(int j = i;j < N; j += i) {
f[j] += 1ll * phi[i] * i + (i == 1);
}
}
}
void solve() {
Euler();
int T;
cin >> T;
while(T--) {
int n;
cin >> n;
cout << f[n] * n / 2 << endl;
}
}
signed main() {
ios_base::sync_with_stdio(false);
//cin.tie(nullptr);
//cout.tie(nullptr);
#ifdef FZT_ACM_LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
signed test_index_for_debug = 1;
char acm_local_for_debug = 0;
do {
if (acm_local_for_debug == '$') exit(0);
if (test_index_for_debug > 20)
throw runtime_error("Check the stdin!!!");
auto start_clock_for_debug = clock();
solve();
auto end_clock_for_debug = clock();
cout << "Test " << test_index_for_debug << " successful" << endl;
cerr << "Test " << test_index_for_debug++ << " Run Time: "
<< double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
cout << "--------------------------------------------------" << endl;
} while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
solve();
#endif
return 0;
}
P5221 Product
求 解 ∏ i = 1 n ∏ j = 1 n l c m ( i , j ) g c d ( i , j ) 求解\prod_{i=1}^n\prod_{j=1}^n\frac{lcm(i,j)}{gcd(i,j)} 求解i=1∏nj=1∏ngcd(i,j)lcm(i,j)
首 先 还 是 把 l c m ( i , j ) 化 简 得 : 首先还是把lcm(i,j)化简得: 首先还是把lcm(i,j)化简得:
∏ i = 1 n ∏ j = 1 n i j [ g c d ( i , j ) ] 2 \prod_{i=1}^n\prod_{j=1}^n\frac{ij}{[gcd(i,j)]^2} i=1∏nj=1∏n[gcd(i,j)]2ij
∏ i = 1 n ∏ j = 1 n i j ∗ ∏ i = 1 n ∏ j = 1 n 1 [ g c d ( i , j ) ] 2 \prod_{i=1}^n\prod_{j=1}^nij*\prod_{i=1}^n\prod_{j=1}^n\frac{1}{[gcd(i,j)]^2} i=1∏nj=1∏nij∗i=1∏nj=1∏n[gcd(i,j)]21
我 们 很 容 易 推 出 前 半 部 分 的 数 值 为 ( n ! ) 2 n , 后 半 部 分 的 值 就 是 ∏ i = 1 n ∏ j = 1 n [ g c d ( i , j ) ] 2 的 逆 元 的 平 方 。 \blue{我们很容易推出前半部分的数值为(n!)^{2n },后半部分的值就是\prod_{i=1}^n\prod_{j=1}^n[gcd(i,j)]^2的逆元的平方。} 我们很容易推出前半部分的数值为(n!)2n,后半部分的值就是∏i=1n∏j=1n[gcd(i,j)]2的逆元的平方。
所 以 现 在 求 解 : 所以现在求解: 所以现在求解:
∏ i = 1 n ∏ j = 1 n g c d ( i , j ) \prod_{i=1}^n\prod_{j=1}^ngcd(i,j) i=1∏nj=1∏ngcd(i,j)
∏ k = 1 n ∏ i = 1 n ∏ j = 1 n k [ g c d ( i , j ) = k ] \prod_{k=1}^n\prod_{i=1}^n\prod_{j=1}^nk[gcd(i,j)=k] k=1∏ni=1∏nj=1∏nk[gcd(i,j)=k]
∏ k = 1 n k ∑ i = 1 n ∑ j = 1 n [ g c d ( i , j ) = k ] \prod_{k=1}^nk^{\sum_{i=1}^n\sum_{j=1}^n[gcd(i,j)=k]} k=1∏nk∑i=1n∑j=1n[gcd(i,j)=k]
这 个 式 子 的 变 换 , 本 来 是 [ 1 , n ] 中 所 有 的 g c d 累 乘 , 然 后 我 们 单 独 把 g c d ( i , j ) = k 的 拿 出 来 , k 会 有 [ 1 , n ] 的 范 围 , 然 后 我 们 再 将 这 些 k 累 乘 就 会 达 到 之 前 的 效 果 。 这个式子的变换,本来是[1,n]中所有的gcd累乘,然后我们单独把gcd(i,j)=k的拿出来,k会有[1,n]的范围,然后我们再将这些k累乘就会达到之前的效果。 这个式子的变换,本来是[1,n]中所有的gcd累乘,然后我们单独把gcd(i,j)=k的拿出来,k会有[1,n]的范围,然后我们再将这些k累乘就会达到之前的效果。
不 过 , [ 1 , n ] 中 的 g c d 不 单 单 只 有 一 个 , 可 能 会 有 多 个 相 同 的 g c d , 所 以 变 换 之 后 的 式 子 里 还 需 要 统 计 g c d = k 出 现 的 次 数 , 那 只 需 要 将 他 们 累 加 即 可 。 不过,[1,n]中的gcd不单单只有一个,可能会有多个相同的gcd,所以变换之后的式子里还需要统计gcd=k出现的次数,那只需要将他们累加即可。 不过,[1,n]中的gcd不单单只有一个,可能会有多个相同的gcd,所以变换之后的式子里还需要统计gcd=k出现的次数,那只需要将他们累加即可。
所 以 没 毛 病 。 继 续 : 所以没毛病。继续: 所以没毛病。继续:
∏ k = 1 n k ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ n k ⌋ [ g c d ( i , j ) = 1 ] \prod_{k=1}^nk^{\sum_{i=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\sum_{j=1}^{\left \lfloor \frac{n}{k} \right \rfloor}[gcd(i,j)=1]} k=1∏nk∑i=1⌊kn⌋∑j=1⌊kn⌋[gcd(i,j)=1]
∏ k = 1 n k ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ n k ⌋ ∑ d ∣ i d ∣ j μ ( d ) \prod_{k=1}^nk^{\sum_{i=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\sum_{j=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\sum_{d|i\;d|j}\mu(d)} k=1∏nk∑i=1⌊kn⌋∑j=1⌊kn⌋∑d∣id∣jμ(d)
枚 举 d : 枚举d: 枚举d:
∏ k = 1 n k ∑ d = 1 ⌊ n k ⌋ μ ( d ) ∑ i = 1 ⌊ n k d ⌋ ∑ j = 1 ⌊ n k d ⌋ 1 \prod_{k=1}^nk^{\sum_{d=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\mu(d)\sum_{i=1}^{\left \lfloor \frac{n}{kd} \right \rfloor}\sum_{j=1}^{\left \lfloor \frac{n}{kd} \right \rfloor}1} k=1∏nk∑d=1⌊kn⌋μ(d)∑i=1⌊kdn⌋∑j=1⌊kdn⌋1
∏ k = 1 n k ∑ d = 1 ⌊ n k ⌋ μ ( d ) ( ⌊ n k d ⌋ ) 2 \red{\prod_{k=1}^nk^{\sum_{d=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\mu(d)(\left \lfloor \frac{n}{kd} \right \rfloor)^2}} k=1∏nk∑d=1⌊kn⌋μ(d)(⌊kdn⌋)2
最 终 答 案 为 : 最终答案为: 最终答案为:
( n ! ) 2 n ∏ k = 1 n k ∑ d = 1 ⌊ n k ⌋ μ ( d ) ( ⌊ n k d ⌋ ) 2 \red{(n!)^{2n}\prod_{k=1}^nk^{\sum_{d=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\mu(d)(\left \lfloor \frac{n}{kd} \right \rfloor)^2}} (n!)2nk=1∏nk∑d=1⌊kn⌋μ(d)(⌊kdn⌋)2
O ( n ) 处 理 μ 的 前 缀 和 , n 询 问 指 数 的 分 块 , 可 以 用 欧 拉 降 幂 优 化 , 总 时 间 复 杂 度 为 O ( n + n l o g 2 n \red{O(n)处理\mu的前缀和,\sqrt n询问指数的分块,可以用欧拉降幂优化,总时间复杂度为O(n+nlog_2n} O(n)处理μ的前缀和,n询问指数的分块,可以用欧拉降幂优化,总时间复杂度为O(n+nlog2n
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;
#define INF 0x7f7f7f
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)
// const ll mod = 998244353;
// const ll P = 1e9 + 7;
// const int maxn = 1e5 + 10;
// const double eps = 1e-6;
const int N = 1000010;
const ll mod = 104857601;
bool is_prime[N];
int prime[N];
int mu[N]; // 莫比乌斯函数
int cnt;
int n;
ll fac = 1;
ll quick_pow(ll a, ll b)
{
ll ans = 1;
while(b) {
if(b & 1) ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
}
void Mobi() // 莫比乌斯函数初始化
{
mu[1] = 1;
is_prime[0] = is_prime[1] = true;
for(int i = 2;i <= n; i++) {
if (!is_prime[i]) {
mu[i] = -1;
prime[++cnt] = i;
}
for (int j = 1; j <= cnt && i * prime[j] <= n; j++) {
is_prime[i * prime[j]] = true;
if (i % prime[j] == 0) {
mu[i * prime[j]] = 0;
break;
}
mu[i * prime[j]] = -mu[i];
}
mu[i] = mu[i - 1] + mu[i];
fac = fac * i % mod;
}
}
ll Ans() {
ll ans = 1;
for(int k = 1;k <= n; k++) {
ll p = 0;
int t = n / k;
for(int l = 1, r;l <= t; l = r + 1) {
r = min(t, t / (t / l));
p = (p + (mu[r] - mu[l - 1] + mod - 1) * (t / l) % (mod - 1) * (t / l) % (mod - 1)) % (mod - 1);
}
ans = ans * quick_pow(k, p) % mod;
}
ll k = quick_pow(ans, mod - 2);
fac = quick_pow(fac, n);
return quick_pow(k, 2) * fac % mod * fac % mod;
}
void solve() {
cin >> n;
Mobi();
cout << Ans() << endl;
}
signed main() {
ios_base::sync_with_stdio(false);
//cin.tie(nullptr);
//cout.tie(nullptr);
#ifdef FZT_ACM_LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
signed test_index_for_debug = 1;
char acm_local_for_debug = 0;
do {
if (acm_local_for_debug == '$') exit(0);
if (test_index_for_debug > 20)
throw runtime_error("Check the stdin!!!");
auto start_clock_for_debug = clock();
solve();
auto end_clock_for_debug = clock();
cout << "Test " << test_index_for_debug << " successful" << endl;
cerr << "Test " << test_index_for_debug++ << " Run Time: "
<< double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
cout << "--------------------------------------------------" << endl;
} while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
solve();
#endif
return 0;
}
HDU 6588 Function
求 解 ∑ i = 1 n g c d ( ⌊ i 3 ⌋ , i ) 求解\sum_{i=1}^ngcd(\left \lfloor \sqrt[3]i \right \rfloor,i) 求解i=1∑ngcd(⌊3i⌋,i)
我 们 先 将 这 个 一 重 和 式 转 化 为 二 重 和 式 , 得 : 我们先将这个一重和式转化为二重和式,得: 我们先将这个一重和式转化为二重和式,得:
∑ a = 1 ⌊ n 3 ⌋ ∑ i = 1 n g c d ( a , i ) [ ⌊ i 3 ⌋ = a ] \sum_{a=1}^{\left \lfloor \sqrt[3]n \right \rfloor}\sum_{i=1}^ngcd(a,i)[\left \lfloor \sqrt[3]i \right \rfloor=a] a=1∑⌊3n⌋i=1∑ngcd(a,i)[⌊3i⌋=a]
我 们 来 看 这 个 式 子 , 只 有 当 ⌊ i 3 ⌋ = a 时 , 才 会 有 对 答 案 的 贡 献 为 g c d ( a , i ) , 所 以 a ≤ ⌊ i 3 ⌋ < a + 1 , a 3 ≤ i ≤ ( a + 1 ) 3 − 1 , 所 以 上 式 转 化 为 : 我们来看这个式子,只有当\left \lfloor \sqrt[3]i \right \rfloor=a时,才会有对答案的贡献为gcd(a,i),所以\blue{a \leq \left \lfloor \sqrt[3]i \right \rfloor < a+1,a^3 \leq i \leq (a+1)^3-1},所以上式转化为: 我们来看这个式子,只有当⌊3i⌋=a时,才会有对答案的贡献为gcd(a,i),所以a≤⌊3i⌋<a+1,a3≤i≤(a+1)3−1,所以上式转化为:
∑ a = 1 ⌊ n 3 ⌋ ∑ i = a 3 m i n ( n , ( a + 1 ) 3 − 1 ) g c d ( a , i ) \red{\sum_{a=1}^{\left \lfloor \sqrt[3]n \right \rfloor}\sum_{i=a^3}^{min(n,(a+1)^3-1)}gcd(a,i)} a=1∑⌊3n⌋i=a3∑min(n,(a+1)3−1)gcd(a,i)
然 后 我 们 将 这 个 二 重 和 式 拆 开 得 : 然后我们将这个二重和式拆开得: 然后我们将这个二重和式拆开得:
∑ a = 1 ⌊ n 3 ⌋ − 1 ∑ i = a 3 m i n ( n , ( a + 1 ) 3 − 1 ) g c d ( a , i ) + ∑ i = ( ⌊ n 3 ⌋ ) 3 n g c d ( ⌊ n 3 ⌋ , i ) {\color{Brown}\sum_{a=1}^{\left \lfloor \sqrt[3]n \right \rfloor-1}\sum_{i=a^3}^{min(n,(a+1)^3-1)}gcd(a,i)+\sum_{i=(\left \lfloor \sqrt[3]n \right \rfloor)^3}^ngcd(\left \lfloor \sqrt[3]n \right \rfloor, i)} a=1∑⌊3n⌋−1i=a3∑min(n,(a+1)3−1)gcd(a,i)+i=(⌊3n⌋)3∑ngcd(⌊3n⌋,i)
令 n 3 = N , 并 使 a = i , i = j ( 好 看 一 点 ) 得 : 令\sqrt[3]n=N,并使a=i,i=j(好看一点)得: 令3n=N,并使a=i,i=j(好看一点)得:
∑ i = 1 N − 1 ∑ j = i 3 ( i + 1 ) 3 − 1 g c d ( i , j ) + ∑ j = N 3 n g c d ( N , j ) {\color{Brown}\sum_{i=1}^{N-1}\sum_{j=i^3}^{(i+1)^3-1}gcd(i,j)+\sum_{j=N^3}^ngcd(N, j)} i=1∑N−1j=i3∑(i+1)3−1gcd(i,j)+j=N3∑ngcd(N,j)
先 计 算 前 半 部 分 : 先计算前半部分: 先计算前半部分:
$$$$