常见转化:
1. ∑ni=1∑j|ij=∑ni=1i∗⌊ni⌋=∑ni=1⌊ni⌋∗(1+⌊ni⌋)2 ∑ i = 1 n ∑ j | i j = ∑ i = 1 n i ∗ ⌊ n i ⌋ = ∑ i = 1 n ⌊ n i ⌋ ∗ ( 1 + ⌊ n i ⌋ ) 2
2. ∑i|nϕ(i)=n,ϕ(n)=n−∑i|n,i<n ∑ i | n ϕ ( i ) = n , ϕ ( n ) = n − ∑ i | n , i < n
3. [n=1]=∑i|nμ(i) [ n = 1 ] = ∑ i | n μ ( i )
4. ∑ni=1∑j|if(j)=∑ni=1∑⌊ni⌋j=1f(j) ∑ i = 1 n ∑ j | i f ( j ) = ∑ i = 1 n ∑ j = 1 ⌊ n i ⌋ f ( j )
5. μ2(i)=∑j2|iμ(j) μ 2 ( i ) = ∑ j 2 | i μ ( j )
6. [gcd(i,j)]=∑d|i,d|jμ(d) [ g c d ( i , j ) ] = ∑ d | i , d | j μ ( d )
51NOD 欧拉函数之和
记 Φ(n)=∑ni=1ϕ(i) Φ ( n ) = ∑ i = 1 n ϕ ( i ) , 而 n=∑i|nϕ(i)=>ϕ(n)=n−∑i|n,i<nϕ(i) n = ∑ i | n ϕ ( i ) => ϕ ( n ) = n − ∑ i | n , i < n ϕ ( i )
所以
Φ(n)=∑ni=1ϕ(i)=∑ni=1(i−∑j|i,j<iϕ(j))=∑ni=1i−∑ni=1∑j|i,j<iϕ(j) Φ ( n ) = ∑ i = 1 n ϕ ( i ) = ∑ i = 1 n ( i − ∑ j | i , j < i ϕ ( j ) ) = ∑ i = 1 n i − ∑ i = 1 n ∑ j | i , j < i ϕ ( j )
=n∗(n+1)2−∑ni=2∑j|i,j<iϕ(j)=n∗(n+1)2−∑ni=2∑⌊ni⌋j=1ϕ(j) = n ∗ ( n + 1 ) 2 − ∑ i = 2 n ∑ j | i , j < i ϕ ( j ) = n ∗ ( n + 1 ) 2 − ∑ i = 2 n ∑ j = 1 ⌊ n i ⌋ ϕ ( j )
故得到递推式: Φ(n)=n∗(n+1)2−∑ni=2Φ(⌊ni⌋) Φ ( n ) = n ∗ ( n + 1 ) 2 − ∑ i = 2 n Φ ( ⌊ n i ⌋ ) ,后面部分只有 n−−√ n 种取值,因此直接预处理前 n3/2 n 3 / 2 ,后面的暴力递归,复杂度 O(n3/2) O ( n 3 / 2 ) 。
#define others
#ifdef poj
#include
#include
#include
#include
#include
#include
#include
#include
#include
#endif // poj
#ifdef others
#include
#include
#include
#endif // others
//#define file
#define all(x) x.begin(), x.end()
using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;
#define eps 1e-8
const double pi = acos(-1.0);
typedef long long LL;
typedef int DLL;
typedef unsigned long long ULL;
void umax(LL &a, LL b) {
a = max(a, b);
}
void umin(LL &a, LL b) {
a = min(a, b);
}
int dcmp(double x) {
return fabs(x) <= eps?0:(x > 0?1:-1);
}
void file() {
freopen("data_in.txt", "r", stdin);
freopen("data_out.txt", "w", stdout);
}
const LL mod = 1e9+7;
LL Pow(LL a,LL b) {
LL res=1;
a%=mod;
for(; b; b>>=1) {
if(b&1)res=res*a%mod;
a=a*a%mod;
}
return res;
}
//
//void print(DLL x) {
// if(x < 0) {
// x = -x;
// putchar('-');
// }
// if(x > 9) print(x/10);
// putchar(x%10 + '0');
//}
//#define iostart
#define pb(x) push_back(x)
namespace solver {
const int maxn = 1e7+10;
int cnt;
int p[maxn/10];
bool tag[maxn];
LL md = Pow(2, mod-2);
LL phi[maxn];
void shai() {
cnt = 0;
phi[1] = 1;
for (int i = 2; i < maxn; i++) {
if(!tag[i]) {
phi[i] = i - 1;
p[cnt++] = i;
}
for (int j = 0; j < cnt && i * p[j] < maxn; j++){
tag[i*p[j]] = 1;
if(i % p[j] == 0){
phi[i*p[j]] = phi[i] * p[j];
break;
}
phi[i*p[j]] = phi[i] * (p[j] - 1);
}
}
for (int i = 1; i < maxn; i++){
phi[i] += phi[i-1];
if (phi[i] >= mod) phi[i] %= mod;
}
}
LL getv(LL n) {
n %= mod;
return ((n * (n + 1))%mod*md)%mod;
}
unordered_map mp;
LL get(LL n) {
if (n < maxn) {
return phi[n];
}
if (mp.count(n)) {
return mp[n];
}
LL ans = getv(n);
for (LL i = 2, last; i <= n; i=last+1) {
last = n / (n / i);
ans -= 1LL*(last - i + 1)%mod * get(n/i)%mod;
ans %= mod;
ans += mod;
ans %= mod;
// if (ans < 0) ans += mod;
}
return mp[n] = ans;
}
void solve() {
shai();
LL x;
scanf("%lld", &x);
cout << get(x);
}
}
int main() {
#ifdef iostart
ios::sync_with_stdio(0);
cin.tie(0);
#endif // iostart
// file();
solver::solve();
return 0;
}
51NOD 莫比乌斯函数之和
定义M(n)=∑ni=1μ(i) 定 义 M ( n ) = ∑ i = 1 n μ ( i ) ,那么
1=∑ni=1[i=1]=∑ni=1∑j|iμ(j)=∑ni=1∑⌊ni⌋j=1μ(j)=∑ni=1M(⌊ni⌋) 1 = ∑ i = 1 n [ i = 1 ] = ∑ i = 1 n ∑ j | i μ ( j ) = ∑ i = 1 n ∑ j = 1 ⌊ n i ⌋ μ ( j ) = ∑ i = 1 n M ( ⌊ n i ⌋ )
故 M(n)=1−∑ni=2M(⌊ni⌋) M ( n ) = 1 − ∑ i = 2 n M ( ⌊ n i ⌋ )
后面部分只有 n−−√ n 种取值,因此直接预处理前 n3/2 n 3 / 2 ,后面的暴力递归,复杂度 O(n3/2) O ( n 3 / 2 ) 。
#define others
#ifdef poj
#include
#include
#include
#include
#include
#include
#include
#include
#include
#endif // poj
#ifdef others
#include
#include
#include
#endif // others
//#define file
#define all(x) x.begin(), x.end()
using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;
#define eps 1e-8
const double pi = acos(-1.0);
typedef long long LL;
typedef int DLL;
typedef unsigned long long ULL;
void umax(LL &a, LL b) {
a = max(a, b);
}
void umin(LL &a, LL b) {
a = min(a, b);
}
int dcmp(double x) {
return fabs(x) <= eps?0:(x > 0?1:-1);
}
void file() {
freopen("data_in.txt", "r", stdin);
freopen("data_out.txt", "w", stdout);
}
const LL mod = 1e9+7;
LL Pow(LL a,LL b) {
LL res=1;
a%=mod;
for(; b; b>>=1) {
if(b&1)res=res*a%mod;
a=a*a%mod;
}
return res;
}
//
//void print(DLL x) {
// if(x < 0) {
// x = -x;
// putchar('-');
// }
// if(x > 9) print(x/10);
// putchar(x%10 + '0');
//}
//#define iostart
#define pb(x) push_back(x)
namespace solver {
const int maxn = 1e7+10;
int cnt;
int p[maxn/10];
bool tag[maxn];
int mob[maxn];
void shai() {
cnt = 0;
mob[1] = 1;
for (int i = 2; i < maxn; i++) {
if(!tag[i]) {
mob[i] = -1;
p[cnt++] = i;
}
for (int j = 0; j < cnt && i * p[j] < maxn; j++){
tag[i*p[j]] = 1;
if(i % p[j] == 0){
mob[i*p[j]] = 0;
break;
}
mob[i*p[j]] = -mob[i];
}
}
for (int i = 1; i < maxn; i++){
mob[i] += mob[i-1];
}
}
unordered_map mp;
LL get(LL n) {
if (n < maxn) {
return mob[n];
}
if (mp.count(n)) {
return mp[n];
}
LL ans = 1;
for (LL i = 2, last; i <= n; i=last+1) {
last = n / (n / i);
ans -= (last - i + 1) * get(n/i);
}
return mp[n] = ans;
}
void solve() {
shai();
LL l, r;
scanf("%lld%lld", &l, &r);
cout << get(r) - get(l-1);
}
}
int main() {
#ifdef iostart
ios::sync_with_stdio(0);
cin.tie(0);
#endif // iostart
// file();
solver::solve();
return 0;
}
一般化:
对于数论函数 f(i) f ( i ) , 想要求解
S(n)=∑ni=1f(i) S ( n ) = ∑ i = 1 n f ( i ) ,那么找到一个合适的数论函数 g(n) g ( n ) ,可以得到递推式:
g(1)S(n)=∑ni=1(f∗g)(i)−∑ni=2g(i)S(⌊ni⌋) g ( 1 ) S ( n ) = ∑ i = 1 n ( f ∗ g ) ( i ) − ∑ i = 2 n g ( i ) S ( ⌊ n i ⌋ ) 。
如果 f(i) f ( i ) 是积性,那么可以 O(n2/3) O ( n 2 / 3 ) ,否则暴力递归 O(n3/4) O ( n 3 / 4 ) 。
可以发现取 g(n)=1 g ( n ) = 1 即可得到上述欧拉函数与莫比乌斯函数前缀和的递推公式。
TODO:
2018 ACM-ICPC 沈阳网络赛C Convex hull
2018ACM-ICPC徐州网络赛 D Easy Math
提供几个优秀的学习来源:
tls的博客:https://blog.csdn.net/skywalkert/article/details/50500009
吉利爷的博客:http://jiruyi910387714.is-programmer.com/posts/195270.html
2016国家队论文-积性函数求和的几种方法