概述
参考:大佬1 大佬2 大佬3 大佬4
P3455 [POI2007]ZAP-Queries
求
解
∑
i
=
1
n
∑
j
=
1
m
[
g
c
d
(
i
,
j
)
=
k
]
求解sum_{i=1}^nsum_{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}^nsum_{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 + Tsqrt 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_{pin prime}sum_{i=1}^nsum_{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_{pin 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+Tsqrt 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 rfloorsum_{p|T;pin 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;pin 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_{pin prime}sum_{i=1}^nsum_{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 + Tsqrt 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}^nsum_{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}^nsum_{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}^nsum_{j=1}^nsum_{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}^nksum_{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}^nksum_{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}^nksum_{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}^nksum_{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}^nsum_{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}^nvarphi (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}^nvarphi (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}^nsum_{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}^nsum_{j=1}^mfrac{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}^nsum_{j=1}^mfrac{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)}ksum_{i=1}^{left lfloor frac{n}{k} right rfloor}sum_{j=1}^{left lfloor frac{m}{k} right rfloor}ijsum_{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)}ksum_{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}idsum_{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)}ksum_{d=1}^{min(left lfloor frac{n}{k} right rfloor,left lfloor frac{m}{k} right rfloor)}mu(d)d^2sum_{i=1}^{left lfloor frac{n}{kd} right rfloor}isum_{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 lfloorfrac{n}{k}right rfloor,left lfloorfrac{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}^nsum_{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}^nsum_{i=1}^nsum_{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}^nksum_{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^3sum_{i=1}^{left lfloor frac{n}{k} right rfloor}sum_{j=1}^{left lfloor frac{n}{k} right rfloor}ijsum_{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^3sum_{d=1}^{left lfloor frac{n}{k} right rfloor}mu(d)sum_{i=1}^{left lfloor frac{n}{kd} right rfloor}idsum_{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^3sum_{d=1}^{left lfloor frac{n}{k} right rfloor}mu(d)d^2sum_{i=1}^{left lfloor frac{n}{kd} right rfloor}isum_{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^3sum_{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+nsqrt 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^2sum_{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^2red{(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^2red{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^2varphi (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}^nsum_{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_{xyleq 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^2varphi(i),f(i)=i^2varphi(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^2varphi(d)frac{x^2}{d^2}=x^2sum_{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^2varphi (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}^nsum_{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}^nsum_{j=1}^msum_{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}^nsum_{y=1}^mleft lfloor frac{n}{x} right rfloorleft 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}^nsum_{j=1}^mleft lfloor frac{n}{i} right rfloorleft 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}^nsum_{j=1}^mleft lfloor frac{n}{i} right rfloorleft lfloor frac{n}{j} right rfloorsum_{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}^nsum_{j=1}^mleft lfloor frac{n}{i} right rfloorleft 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 lfloorfrac{m}{d}right rfloor}left lfloor frac{n}{id} right rfloorleft 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 rfloorsum_{j=1}^{left lfloorfrac{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}^xleft 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(nsqrt n)处理f,O(sqrt n)询问分块,总复杂度为O(nsqrt n+Tsqrt 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}^nsum_{j=1}^msum_{d|i;d|j}d[sum_{d|i;d|j}dleq 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}^nsum_{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}^nsum_{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}^nsum_{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 rfloorsum_{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)+Tsqrt n; logn} O(n)处理μ,O(nlogn)处理F,对于每次询问的a值可以离线排序,树状数组维护f,处理时间为O(nlog2n),O(nlogn)询问分块,总时间复杂度为O(nlog2n)+Tnlogn
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;
#define INF 0x3f3f3f3f
#define lc u << 1
#define rc u << 1 | 1
#define m (l + r) / 2
#define mid (t[u].l + t[u].r) / 2
#define lowbit(x) x & (-x)
#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 mod = 1e9 + 7;
// const double eps = 1e-6;
// const double PI = acos(-1);
// const double R = 0.57721566490153286060651209;
const int N = 1e5 + 1;
ll mod = (1ll * 1) << 31;
struct node {
int id;
ll data;
}F[N];
struct Node {
int nn, mm, id;
ll a;
}q[N];
int cnt, prime[N];
bool is_prime[N];
int mu[N];
bool cmp_F(node a, node b) {
return a.data < b.data;
}
bool cmp_Q(Node a, Node b) {
return a.a < b.a;
}
inline void init()
{
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++) {
F[i].id = i;
for(int j = 1;j * i < N; j++) {
F[i * j].data += i;
}
}
sort(F + 1, F + N, cmp_F);
}
ll t[N];
ll ans[N];
inline void add(int x, int v) {
while(x < N) {
t[x] = (t[x] + v) % mod;
if(t[x] > mod)
t[x] %= mod;
x += lowbit(x);
}
}
inline ll query(int x) {
ll ans = 0;
while(x) {
ans = (ans + t[x]) % mod;
if(ans > mod)
ans %= mod;
x -= lowbit(x);
}
return ans;
}
inline ll Calc(int nn, int mm) {
if(nn > mm)
swap(nn, mm);
ll ans = 0;
for(int l = 1, r;l <= nn; l = r + 1) {
r = min(nn / (nn / l), mm / (mm / l));
ans = (ans + 1ll * (nn / l) * (mm / l) % mod * (query(r) - query(l - 1)) % mod) % mod;
}
return ans;
}
//struct SegMent {
// int l, r;
// int sum;
//}t[N << 2];
//
//void push_up(int u) {
// t[u].sum = t[lc].sum + t[rc].sum;
//}
//
//void build(int u, int l, int r) {
// t[u].l = l;
// t[u].r = r;
// if(l == r) {
// t[u].sum = a[l];
// return ;
// }
// build(lc, l, m);
// build(rc, m + 1, r);
// push_up(u);
//}
//
//void update(int u, int p, int v) {
// if(t[u].l == t[u].r) {
// t[u].sum += v;
// return ;
// }
// if(p <= mid) update(lc, p, v);
// else update(rc, p, v);
// push_up(u);
//}
//
//int query(int u, int ql, int qr) {
// if(ql <= t[u].l && t[u].r <= qr) {
// return t[u].sum;
// }
// int ans = 0;
// if(ql <= mid)
// ans += query(lc, ql, qr);
// if(qr > mid)
// ans += query(rc, ql, qr);
// return ans;
//}
void solve() {
init();
int T;
scanf("%d",&T);
for(int i = 1;i <= T; i++) {
scanf("%d%d%lld",&q[i].nn,&q[i].mm, &q[i].a);
q[i].id = i;
}
sort(q + 1, q + T + 1, cmp_Q);
int now = 1;
for(int i = 1;i <= T; i++) {
while(now < N && F[now].data <= q[i].a) {
for(int j = 1;j * F[now].id < N; j++) {
add(j * F[now].id, mu[j] * F[now].data);
}
now++;
}
ans[q[i].id] = (Calc(q[i].nn, q[i].mm) % mod + mod) % mod;
}
for(int i = 1;i <= T; i++) {
printf("%lldn",ans[i]);
}
}
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;
}
P3172 [CQOI2015]选数
求 解 ∑ i = L H ∑ j = L H . . . ∑ x = L H [ g c d ( i , j . . . x ) = k ] 求解sum_{i=L}^Hsum_{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}^rmu(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}^rvarepsilon (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(nfrac{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}^Msum_{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}^Msum_{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}^Mksum_{i=1}^{left lfloor frac{M}{k} right rfloor}sum_{j=1}^{left lfloor frac{M}{k} right rfloor}cnt_{ik} ⋅cnt_{jk} ⋅i ⋅jsum_{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}^Mksum_{d=1}^{left lfloor frac{M}{k} right rfloor}mu(d)sum_{i=1}^{left lfloor frac{M}{kd} right rfloor}cnt_{ikd} ⋅idsum_{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}^Mksum_{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)^2sum_{k|T}mu(k)k^2frac{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)^2sum_{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}^nfrac{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}^nsum_{i=1}^nfrac{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}^nsum_{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 ] nsum_{k=1}^nsum_{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 ] nsum_{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 ) nsum_{k|n}sum_{i=1}^kisum_{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 nsum_{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 nsum_{k|n}sum_{d|k}mu(d)dsum_{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 nsum_{k|n}sum_{d|k}mu(d)dfrac{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+Tsqrt 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}^nprod_{j=1}^nfrac{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}^nprod_{j=1}^nfrac{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}^nprod_{j=1}^nij*prod_{i=1}^nprod_{j=1}^nfrac{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}^nprod_{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}^nprod_{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}^nprod_{i=1}^nprod_{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}^nsum_{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)
先 计 算 前 半 部 分 : 先计算前半部分: 先计算前半部分:
∣ − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − ∣ |--------------------------------| ∣−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−∣
HDU 6833 A Very Easy Math Problem
求
解
∑
a
1
=
1
n
∑
a
2
=
1
n
.
.
.
∑
a
x
=
1
n
(
∏
j
=
1
x
a
j
k
)
f
(
g
c
d
(
a
1
,
a
2
.
.
.
a
x
)
)
g
c
d
(
a
1
,
a
2
.
.
.
a
x
)
求解sum_{a_1=1}^nsum_{a_2=1}^n...sum_{a_x=1}^nleft(prod_{j=1}^xa_j^kright)f(gcd(a_1,a_2...a_x))gcd(a_1,a_2...a_x)
求解a1=1∑na2=1∑n...ax=1∑n(j=1∏xajk)f(gcd(a1,a2...ax))gcd(a1,a2...ax)
令
d
=
g
c
d
(
a
1
,
a
2
.
.
.
a
x
)
得
:
令d=gcd(a_1,a_2...a_x)得:
令d=gcd(a1,a2...ax)得:
∑ a 1 = 1 n ∑ a 2 = 1 n . . . ∑ a x = 1 n ( ∏ j = 1 x a j k ) f ( d ) d sum_{a_1=1}^nsum_{a_2=1}^n...sum_{a_x=1}^nleft(prod_{j=1}^xa_j^kright)f(d)d a1=1∑na2=1∑n...ax=1∑n(j=1∏xajk)f(d)d
枚 举 d 得 : 枚举d得: 枚举d得:
∑ d = 1 n d f ( d ) ∑ a 1 = 1 n ∑ a 2 = 1 n . . . ∑ a x = 1 n ( ∏ j = 1 x a j k ) [ g c d ( a 1 , a 2 . . . a x ) = d ] sum_{d=1}^ndf(d)sum_{a_1=1}^nsum_{a_2=1}^n...sum_{a_x=1}^nleft(prod_{j=1}^xa_j^kright)[gcd(a_1,a_2...a_x)=d] d=1∑ndf(d)a1=1∑na2=1∑n...ax=1∑n(j=1∏xajk)[gcd(a1,a2...ax)=d]
∑ d = 1 n d k x + 1 f ( d ) ∑ a 1 = 1 ⌊ n d ⌋ ∑ a 2 = 1 ⌊ n d ⌋ . . . ∑ a x = 1 ⌊ n d ⌋ ( ∏ j = 1 x a j k ) [ g c d ( a 1 , a 2 . . . a x ) = 1 ] sum_{d=1}^nd^{kx+1}f(d)sum_{a_1=1}^{left lfloor frac{n}{d} right rfloor }sum_{a_2=1}^{left lfloor frac{n}{d} right rfloor }...sum_{a_x=1}^{left lfloor frac{n}{d} right rfloor }left(prod_{j=1}^xa_j^kright)[gcd(a_1,a_2...a_x)=1] d=1∑ndkx+1f(d)a1=1∑⌊dn⌋a2=1∑⌊dn⌋...ax=1∑⌊dn⌋(j=1∏xajk)[gcd(a1,a2...ax)=1]
∑ d = 1 n d k x + 1 f ( d ) ∑ a 1 = 1 ⌊ n d ⌋ ∑ a 2 = 1 ⌊ n d ⌋ . . . ∑ a x = 1 ⌊ n d ⌋ ( ∏ j = 1 x a j k ) ∑ t ∣ a 1 t ∣ a 2 . . . t ∣ a x μ ( t ) sum_{d=1}^nd^{kx+1}f(d)sum_{a_1=1}^{left lfloor frac{n}{d} right rfloor }sum_{a_2=1}^{left lfloor frac{n}{d} right rfloor }...sum_{a_x=1}^{left lfloor frac{n}{d} right rfloor }left(prod_{j=1}^xa_j^kright)sum_{t|a_1;t|a2;...;t|a_x}mu(t) d=1∑ndkx+1f(d)a1=1∑⌊dn⌋a2=1∑⌊dn⌋...ax=1∑⌊dn⌋(j=1∏xajk)t∣a1t∣a2...t∣ax∑μ(t)
∑ d = 1 n d k x + 1 f ( d ) ( ∑ i = 1 ⌊ n d ⌋ i k ) x ∑ t ∣ a 1 t ∣ a 2 . . . t ∣ a x μ ( t ) sum_{d=1}^nd^{kx+1}f(d)left (sum_{i=1}^{left lfloor frac{n}{d} right rfloor }i^kright)^xsum_{t|a_1;t|a2;...;t|a_x}mu(t) d=1∑ndkx+1f(d)⎝⎜⎛i=1∑⌊dn⌋ik⎠⎟⎞xt∣a1t∣a2...t∣ax∑μ(t)
枚 举 t 得 : 枚举t得: 枚举t得:
∑ d = 1 n d k x + 1 f ( d ) ∑ t = 1 ⌊ n d ⌋ μ ( t ) ( ∑ i = 1 ⌊ n d t ⌋ ( i t ) k ) x sum_{d=1}^nd^{kx+1}f(d)sum_{t=1}^{left lfloor frac{n}{d} right rfloor }mu(t)left (sum_{i=1}^{left lfloor frac{n}{dt} right rfloor }(it)^kright)^x d=1∑ndkx+1f(d)t=1∑⌊dn⌋μ(t)⎝⎜⎛i=1∑⌊dtn⌋(it)k⎠⎟⎞x
∑ d = 1 n d k x + 1 f ( d ) ∑ t = 1 ⌊ n d ⌋ μ ( t ) t k x ( ∑ i = 1 ⌊ n d t ⌋ i k ) x sum_{d=1}^nd^{kx+1}f(d)sum_{t=1}^{left lfloor frac{n}{d} right rfloor }mu(t)t^{kx}left (sum_{i=1}^{left lfloor frac{n}{dt} right rfloor }i^kright)^x d=1∑ndkx+1f(d)t=1∑⌊dn⌋μ(t)tkx⎝⎜⎛i=1∑⌊dtn⌋ik⎠⎟⎞x
令 T = d t 并 枚 举 T 得 : 令T=dt并枚举T得: 令T=dt并枚举T得:
∑ T = 1 n ( ∑ i = 1 ⌊ n d t ⌋ i k ) x T k x ∑ d ∣ T d f ( d ) μ ( T d ) sum_{T=1}^nleft (sum_{i=1}^{left lfloor frac{n}{dt} right rfloor }i^kright)^xT^{kx}sum_{d|T}df(d)mu(frac{T}{d}) T=1∑n⎝⎜⎛i=1∑⌊dtn⌋ik⎠⎟⎞xTkxd∣T∑df(d)μ(dT)
令 g ( T ) = ∑ d ∣ T d f ( d ) μ ( T d ) , 则 令g(T)=sum_{d|T}df(d)mu(frac{T}{d}),则 令g(T)=∑d∣Tdf(d)μ(dT),则
∑ T = 1 n ( ∑ i = 1 ⌊ n T ⌋ i k ) x T k x g ( T ) sum_{T=1}^nleft (sum_{i=1}^{left lfloor frac{n}{T} right rfloor }i^kright)^xT^{kx}g(T) T=1∑n⎝⎜⎛i=1∑⌊Tn⌋ik⎠⎟⎞xTkxg(T)
O ( n l o g n ) 筛 f 和 g , 并 对 T k x g ( T ) 和 ∑ i = 1 ⌊ n T ⌋ i k 做 前 缀 和 , 最 后 n 分 块 计 算 , 复 杂 度 为 O ( n l o g n + T n ) red{O(nlogn)筛f和g,并对T^{kx}g(T)和sum_{i=1}^{left lfloor frac{n}{T} right rfloor }i^k做前缀和,最后sqrt n分块计算,复杂度为O(nlogn+Tsqrt n)} O(nlogn)筛f和g,并对Tkxg(T)和∑i=1⌊Tn⌋ik做前缀和,最后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 0x3f3f3f3f
#define lowbit(x) x & (-x)
#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 mod = 1e9 + 7;
// const double eps = 1e-6;
// const double pi = acos(-1);
const int N = 2e5 + 10;
ll T, k, x;
int mu[N]; // 莫比乌斯函数
bool is_prime[N];
int prime[N];
int cnt;
ll g[N], f[N];
ll sumG[N], sumi[N];
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 % mod;
}
void Mobi() // 莫比乌斯函数初始化
{
f[1] = mu[1] = 1;
is_prime[0] = is_prime[1] = true;
for(int i = 2;i < N; i++) {
f[i] = 1;
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];
}
}
// 筛f函数
for(int d = 2;d * d < N; d++) {
for(int i = d * d;i < N; i += d * d) {
f[i] = 0;
}
}
// 筛g函数
for(int d = 1;d < N; d++) {
for(int i = d;i < N; i += d) {
g[i] = (g[i] + 1ll * d * f[d] % mod * mu[i / d] % mod + mod) % mod;
}
}
// 处理sumG函数和sumi函数前缀和
for(int i = 1;i < N; i++) {
ll t = quick_pow(i, k);
sumi[i] = (sumi[i - 1] + t) % mod;
sumG[i] = (sumG[i - 1] + quick_pow(t, x) * g[i] % mod) % mod;
}
}
void solve() {
cin >> T >> k >> x;
Mobi();
while(T--) {
int n;
cin >> n;
ll ans = 0;
for(int l = 1, r;l <= n; l = r + 1) {
r = min(n, n / (n / l));
ans = (ans + (sumG[r] - sumG[l - 1] + mod) % mod * quick_pow(sumi[n / l], x) % mod) % mod;
}
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;
}
huntian oy
求 解 ∑ i = 1 n ∑ j = 1 i g c d ( i a − j a , i b − j b ) [ g c d ( i , j ) = 1 ] 求解sum_{i=1}^nsum_{j=1}^igcd(i^a-j^a,i^b-j^b)[gcd(i,j)=1] 求解i=1∑nj=1∑igcd(ia−ja,ib−jb)[gcd(i,j)=1]
g c d ( i a − j a , i b − j b ) = i g c d ( a , b ) − j g c d ( a , b ) gcd(i^a-j^a,i^b-j^b)=i^{gcd(a,b)}-j^{gcd(a,b)} gcd(ia−ja,ib−jb)=igcd(a,b)−jgcd(a,b)
题 目 说 g c d ( a , b ) = 1 , 所 以 那 个 复 杂 的 式 子 直 接 变 成 i − j . 题目说gcd(a,b)=1,所以那个复杂的式子直接变成i-j. 题目说gcd(a,b)=1,所以那个复杂的式子直接变成i−j.
∑ i = 1 n ∑ j = 1 i ( i − j ) [ g c d ( i , j ) = 1 ] sum_{i=1}^nsum_{j=1}^i(i-j)[gcd(i,j)=1] i=1∑nj=1∑i(i−j)[gcd(i,j)=1]
∑ i = 1 n ∑ j = 1 i i [ g c d ( i , j ) = 1 ] − ∑ i = 1 n ∑ j = 1 i j [ g c d ( i , j ) = 1 ] sum_{i=1}^nsum_{j=1}^ii[gcd(i,j)=1]-sum_{i=1}^nsum_{j=1}^ij[gcd(i,j)=1] i=1∑nj=1∑ii[gcd(i,j)=1]−i=1∑nj=1∑ij[gcd(i,j)=1]
左 边 为 与 i 互 质 的 个 数 , 右 边 为 比 i 小 并 且 互 质 的 数 字 和 , 即 为 : 左边为与i互质的个数,右边为比i小并且互质的数字和,即为: 左边为与i互质的个数,右边为比i小并且互质的数字和,即为:
∑ i = 1 n i φ ( i ) − ∑ i = 1 n i φ ( i ) + 1 2 sum_{i=1}^nivarphi (i)-frac{sum_{i=1}^nivarphi (i)+1}{2} i=1∑niφ(i)−2∑i=1niφ(i)+1
∑ i = 1 n i φ ( i ) − 1 2 frac{sum_{i=1}^nivarphi (i)-1}{2} 2∑i=1niφ(i)−1
因 为 n 有 1 e 9 , 所 以 需 要 杜 教 筛 优 化 。 因为n有1e9,所以需要杜教筛优化。 因为n有1e9,所以需要杜教筛优化。
f ∗ g ( n ) = ∑ d ∣ n f ( d ) g ( n d ) = ∑ d ∣ n i d ( d ) ∗ φ ( d ) ∗ g ( n d ) f*g(n)=sum_{d|n}f(d)g(frac{n}{d})=sum_{d|n}id(d)*varphi (d)*g(frac{n}{d}) f∗g(n)=d∣n∑f(d)g(dn)=d∣n∑id(d)∗φ(d)∗g(dn)
很 显 然 , 设 g = i d , 则 : 很显然,设g=id,则: 很显然,设g=id,则:
f ∗ g ( n ) = ∑ d ∣ n φ ( d ) i d ( n ) = n ∑ d ∣ n φ ( d ) = i d ( n ) ( φ ∗ I ) = i d 2 ( n ) = n 2 f*g(n)=sum_{d|n}varphi (d)id(n)=nsum_{d|n}varphi (d)=id(n)(varphi *I)=id^2(n)=n^2 f∗g(n)=d∣n∑φ(d)id(n)=nd∣n∑φ(d)=id(n)(φ∗I)=id2(n)=n2
所 以 得 : S ( n ) = ∑ i = 1 n ( f ∗ g ) i − ∑ i = 2 n g ( i ) S ( n i ) = n ( n + 1 ) ( 2 n + 1 ) 6 − ∑ i = 2 n i S ( n i ) 所以得:S(n)=sum_{i=1}^n(f*g)i-sum_{i=2}^ng(i)S(frac{n}{i})=frac{n(n+1)(2n+1)}{6}-sum_{i=2}^niS(frac{n}{i}) 所以得:S(n)=i=1∑n(f∗g)i−i=2∑ng(i)S(in)=6n(n+1)(2n+1)−i=2∑niS(in)
Code
#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<double, double> pdd;
typedef pair<ll, ll> pll;
#define endl "n"
#define eb emplace_back
#define mem(a, b) memset(a , b , sizeof(a))
const ll INF = 0x3f3f3f3f;
// const ll mod = 998244353;
const ll mod = 1e9 + 7;
const double eps = 1e-6;
const double PI = acos(-1);
const double R = 0.57721566490153286060651209;
template<typename T>
inline void read(T &a) {char c = getchar();T x = 0, f = 1;
while (!isdigit(c)) {if (c == '-')f = -1;c = getchar();}
while (isdigit(c)) {x = (x << 1) + (x << 3) + c - '0';c = getchar();}a = f * x;
}
const int N = 1e6 + 10;
bool is_prime[N];
int prime[N], cnt;
int phi[N];
ll sum_i_phi[N];
void init() {
phi[1] = 1;
for(int i = 2;i < N; i++) {
if(!is_prime[i]) prime[++cnt] = i, phi[i] = i - 1;
for(int j = 1;j <= cnt && i * prime[j] < N; j++) {
is_prime[i * prime[j]] = 1;
if(i % prime[j] == 0) {
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
else phi[i * prime[j]] = phi[i] * phi[prime[j]];
}
}
for(int i = 1;i < N; i++) {
sum_i_phi[i] = (sum_i_phi[i - 1] + 1ll * i * phi[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 % mod;
}
ll inv2;
ll inv6;
map<ll, ll> mp;
ll S(ll x) {
if(x < N) return sum_i_phi[x];
else if(mp[x]) return mp[x];
ll ans = x * (x + 1) % mod * (2 * x + 1) % mod * inv6 % mod;
for(int l = 2, r;l <= x; l = r + 1) {
r = min(x, x / (x / l));
ans = (ans - 1ll * (r + l) % mod * (r - l + 1) % mod * inv2 % mod * S(x / l)) % mod;
}
return mp[x] = ans;
}
void solve() {
init();
inv2 = quick_pow(2, mod - 2);
inv6 = quick_pow(6, mod - 2);
int _; scanf("%d",&_);
while(_--) {
ll n, a, b; scanf("%lld%lld%lld",&n,&a,&b);
ll ans = (S(n) - 1) % mod;
ans = ans * inv2 % mod;
printf("%lldn",(ans % mod + mod) % mod);
}
}
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 6428 Problem C. Calculate
求 解 ∑ i = 1 A ∑ j = 1 B ∑ k = 1 C ϕ ( g c d ( i , j 2 , k 3 ) ) m o d 2 30 求解sum_{i=1}^Asum_{j=1}^Bsum_{k=1}^Cphi (gcd(i,j^2,k^3));;mod;;2^{30} 求解i=1∑Aj=1∑Bk=1∑Cϕ(gcd(i,j2,k3))mod230
首
先
要
把
ϕ
和
g
c
d
分
开
,
即
ϕ
(
n
)
=
∑
d
∣
n
(
ϕ
∗
μ
)
(
d
)
,
证
明
如
下
:
首先要把phi和gcd分开,即phi(n)=sum_{d|n}(phi*mu)(d),证明如下:
首先要把ϕ和gcd分开,即ϕ(n)=∑d∣n(ϕ∗μ)(d),证明如下:
ϕ
(
n
)
=
(
μ
∗
i
d
)
(
n
)
phi(n)=(mu*id)(n)
ϕ(n)=(μ∗id)(n)
∑ d ∣ n μ ( d ) n d sum_{d|n}mu(d)frac{n}{d} d∣n∑μ(d)dn
∑ d ∣ n μ ( d ) ∑ d ′ ∣ n d ϕ ( d ′ ) sum_{d|n}mu(d)sum_{d'|frac{n}{d}}phi(d') d∣n∑μ(d)d′∣dn∑ϕ(d′)
∑ d d ′ ∣ n μ ( d ) ϕ ( d ′ ) sum_{dd'|n}mu(d)phi(d') dd′∣n∑μ(d)ϕ(d′)
∑ d ∣ n ∑ d ′ ∣ d μ ( d ′ ) ϕ ( d d ′ ) sum_{d|n}sum_{d'|d}mu(d')phi(frac{d}{d'}) d∣n∑d′∣d∑μ(d′)ϕ(d′d)
∑ d ∣ n ( ϕ ∗ μ ) ( d ) sum_{d|n}(phi*mu)(d) d∣n∑(ϕ∗μ)(d)
所 以 原 式 变 为 : 所以原式变为: 所以原式变为:
∑ i = 1 A ∑ j = 1 B ∑ k = 1 C ∑ d ∣ i d ∣ j 2 d ∣ k 3 ( ϕ ∗ μ ) ( d ) sum_{i=1}^Asum_{j=1}^Bsum_{k=1}^Csum_{d|i;d|j^2;d|k^3}(phi*mu)(d) i=1∑Aj=1∑Bk=1∑Cd∣id∣j2d∣k3∑(ϕ∗μ)(d)
∑
d
=
1
A
(
ϕ
∗
μ
)
(
d
)
∑
i
=
1
d
∣
i
A
∑
j
=
1
d
∣
j
2
B
∑
k
=
1
d
∣
k
3
C
1
sum_{d=1}^{A}(phi*mu)(d)sum_{i=1;d|i}^Asum_{j=1;d|j^2}^Bsum_{k=1;d|k^3}^C1
d=1∑A(ϕ∗μ)(d)i=1d∣i∑Aj=1d∣j2∑Bk=1d∣k3∑C1
left lceil right rceil
观
察
后
面
式
子
,
对
于
一
个
x
k
,
若
d
∣
x
k
,
先
把
d
分
解
为
∏
p
i
a
i
.
观察后面式子,对于一个x^k,若d|x^k,先把d分解为prod p_i^{a_i}.
观察后面式子,对于一个xk,若d∣xk,先把d分解为∏piai.
则
∏
p
i
a
i
∣
x
k
,
得
∏
p
i
⌈
a
i
k
⌉
∣
x
,
所
以
设
则prod p_i^{a_i}|x^k,得prod p_i^{left lceil frac{a_i}{k} right rceil }|x,所以设
则∏piai∣xk,得∏pi⌈kai⌉∣x,所以设
f k ( n ) = ∏ p i ⌈ a i k ⌉ f_k(n)=prod p_i^{left lceil frac{a_i}{k} right rceil } fk(n)=∏pi⌈kai⌉
则 : 则: 则:
a n s = ∑ d = 1 A ( ϕ ∗ μ ) ( d ) A f 1 ( d ) B f 2 ( d ) C f 3 ( d ) ans=sum_{d=1}^{A}(phi * mu)(d)frac{A}{f_1(d)}frac{B}{f_2(d)}frac{C}{f_3(d)} ans=d=1∑A(ϕ∗μ)(d)f1(d)Af2(d)Bf3(d)C
对
于
f
k
(
n
)
,
类
似
分
解
n
的
形
式
。
对于f_k(n),类似分解n的形式。
对于fk(n),类似分解n的形式。
分
解
质
因
子
的
过
程
中
,
记
录
质
因
子
的
指
数
,
每
次
质
因
子
+
1
时
,
若
%
k
=
1
时
,
说
明
该
向
上
取
整
了
,
于
是
f
k
(
n
)
∗
=
该
质
因
子
.
分解质因子的过程中,记录质因子的指数,每次质因子+1时,若%k=1时,说明该向上取整了,于是f_k(n)*=该质因子.
分解质因子的过程中,记录质因子的指数,每次质因子+1时,若%k=1时,说明该向上取整了,于是fk(n)∗=该质因子.
由 于 ϕ 和 μ 都 是 积 性 函 数 , 卷 积 之 后 还 是 积 性 函 数 , 设 g ( d ) = ( ϕ ∗ μ ) ( d ) , 则 由于phi和mu都是积性函数,卷积之后还是积性函数,设g(d)=(phi*mu)(d),则 由于ϕ和μ都是积性函数,卷积之后还是积性函数,设g(d)=(ϕ∗μ)(d),则
ϕ ( n ) = ∑ d ∣ n g ( d ) phi(n)=sum_{d|n}g(d) ϕ(n)=d∣n∑g(d)
那 么 可 以 得 : 那么可以得: 那么可以得:
ϕ ( p k ) = ϕ ( p k − 1 ) + g ( p k ) phi(p^k)=phi(p^{k-1})+g(p^k) ϕ(pk)=ϕ(pk−1)+g(pk)
g ( p k ) = ϕ ( p k ) − ϕ ( p k − 1 ) g(p^k)=phi(p^k)-phi(p^{k-1}) g(pk)=ϕ(pk)−ϕ(pk−1)
g ( p k ) = ( p − 1 ) p k − 1 − ( p − 1 ) p k − 2 g(p^k)=(p-1)p^{k-1}-(p-1)p^{k-2} g(pk)=(p−1)pk−1−(p−1)pk−2
g ( p k ) = ( p − 1 ) 2 p k − 2 g(p^k)=(p-1)^2p^{k-2} g(pk)=(p−1)2pk−2
当 我 们 欧 拉 筛 的 过 程 中 : 当我们欧拉筛的过程中: 当我们欧拉筛的过程中:
g ( 1 ) = 1 g(1)=1 g(1)=1
g ( p ) = p − 2 g(p)=p-2 g(p)=p−2
g ( p k ) = ( p − 1 ) 2 p k − 2 g(p^{k})=(p-1)^2p^{k-2} g(pk)=(p−1)2pk−2
g ( p 1 k 1 p 2 k 2 ) = g ( p 1 k 1 ) g ( p 2 k 2 ) g(p_1^{k_1}p_2^{k_2})=g(p_1^{k_1})g(p_2^{k_2}) g(p1k1p2k2)=g(p1k1)g(p2k2)
. . . . . . ...... ......
Code
#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
const ll mod = (1ll << 30);
const int N = 1e7 + 10;
bool is_prime[N];
int prime[N], cnt;
int g[N];
int f1[N], f2[N], f3[N];
int deg[N];
void init() {
f1[1] = f2[1] = f3[1] = g[1] = 1;
for(int i = 2;i < N; i++) {
f1[i] = i;
if(!is_prime[i]) prime[++cnt] = f2[i] = f3[i] = i, g[i] = i - 2, deg[i] = 1;
for(int j = 1;j <= cnt && i * prime[j] < N; j++) {
int now = i * prime[j];
is_prime[now] = 1;
if(i % prime[j] == 0) {
deg[now] = deg[i] + 1;
int num = 1, tmp = i;
while(num <= 3 && tmp % prime[j] == 0) num++, tmp /= prime[j];
if(num == 1) g[now] = g[i] * g[prime[j]];
else if(num == 2) g[now] = g[i / prime[j]] * (prime[j] - 1) * (prime[j] - 1);
else g[now] = g[i] * prime[j];
f2[now] = f2[i] * (deg[now] % 2 == 1 ? prime[j] : 1);
f3[now] = f3[i] * (deg[now] % 3 == 1 ? prime[j] : 1);
break;
}
else {
deg[now] = 1;
f2[now] = f2[i] * f2[prime[j]];
f3[now] = f3[i] * f3[prime[j]];
g[now] = g[i] * g[prime[j]];
}
}
}
}
void solve() {
init();
int _; scanf("%d",&_);
while(_--) {
int A, B, C; scanf("%d%d%d",&A,&B,&C);
ll ans = 0;
for(int d = 1;d <= A; d++) {
ans = (ans + 1ll * g[d] * (A / f1[d]) % mod * (B / f2[d]) % mod * (C / f3[d]) % mod) % mod;
}
printf("%lldn",(ans % mod + mod) % mod);
}
}
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;
}
最后
以上就是怕孤单蜡烛为你收集整理的莫比乌斯反演例题集---(自用)参考:大佬1 大佬2 大佬3 大佬4的全部内容,希望文章能够帮你解决莫比乌斯反演例题集---(自用)参考:大佬1 大佬2 大佬3 大佬4所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复