Processing math: 100%

Several Algorithms of root Complex

I, as a ACMer, always take algorithm complexity into consideration when programming. Today, I introduce you some elegant algorithms of root Complex.

1. s(n)=ni=1ni

Since The range of ni contains at most 2n . There may exist a algorithm of complexity O(n).

1
2
3
4
5
6
7
8
LL getsum(LL n){ // The code is simple and easy to understand
LL sum = 0;
for(LL i=1,j;i<=n;i=j+1){
j = n/(n/i);
sum += (j-i+1)*(n/i);
}
return sum;
}

Actually, s(n) donate the number of positive integer point under graph xy=1.

2. σk(n)=d|ndk

  1. σ0(n) donate the number of divisors.
  2. σ1(n) donate the sum of divisors.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    LL mypow(LL x,LL n){
    LL r = 1;
    while(n){
    if(n&1) r=r*x;
    n>>=1; x=x*x;
    }
    return r;
    }
    LL getr(LL n,LL k){
    LL r = 0,d;
    for(d=1;d*d<n;++d){
    if(n%d==0) r += mypow(d,k) + mypow(n/d,k);
    }
    if(d*d == n) r+=mypow(d,k);
    return r;
    }

The code above is primary and trival.

3. f(n)=ni=1σk(i)

f(n)=ni=1σk(n)=ni=1d|idk=d=1dkni[d|i]=nd=1dknd

If we get ts[n]=ni=1ik, similar to problem 1, we have fllowing C++ code:

1
2
3
4
5
6
7
8
LL getf(LL n){
LL sum = 0;
for(LL i=1,j;i<=n;i=j+1){
j = n/(n/i);
sum += (ts[j]-ts[i-1])*(n/i);
}
return sum;
}

Actuall, we have
ts[n]={n(n+1)2k=1n(n+1)(2n+1)6k=2n2(n+1)24k=3
and for general

1p+2p++np=pk=1(kj=1(1)kjCjkjp)Ck+1n+1

you can see my blog for detail.

4. g(n)=ni=1ϕ(i)

Throughout this blog, ϕ(n) donate the Euler function unless explicitly stated.ϕ(n) counts the positive integers less than or equal to n that are relatively prime to n. Euler’s product formula:
ϕ(n)=np|n(11p)
where the product is over the distinct prime numbers dividing n.

Now, we begin to computer g(n)
g(n)=ni=1ϕ(i)=1xyn,gcd(x,y)=11

we define
gk(n)=ni=1ϕ(i)=1xyn,gcd(x,y)=k1=f(nk)

and ni=1gk(i)=1xyn1=n(n+1)2 So we have

g(n)=n(n+1)2nk=2f(nk)

Similar to problem 1,we have,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const int N=1000006;
LL ans[N];
void init(){
memset(ans,-1,sizeof(ans));
ans[1]=1;ans[2]=2;
}
LL getans(int n){
if(n<N&&ans[n]!=-1) return ans[n];
LL r = n*(n+1)/2;
for(int i=2,j;i<=n;i=j+1){
j = n/(n/i);
r -= (j-i+1)*getans(n/i);
}
if(n<N) ans[n]=r;
return r;
}

5. Problem hdu5608

If
n23n+2=d|nf(d)
calculate
h(n)=ni=1f(i)mod109+7

Since
ni=1d|if(d)=ni=1f(i)ni=ni=1h(ni)
and we have,

ni=1d|if(d)=ni=1n23n+2=ni=1(n1)(n2)=n(n1)(n2)3

by conditon. Hence,
h(n)=n(n1)(n2)3ni=2h(ni)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//#pragma comment(linker,"/STACK:10240000,10240000")
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <string>
#include <bitset>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
#define clr(a,b) memset(a,b,sizeof(a))
#define MP make_pair
#define PB push_back
#define lrt rt<<1
#define rrt rt<<1|1
#define lson l,m,lrt
#define rson m+1,r,rrt
/*------ Welcome to visit blog of dna049: http://dna049.com ------*/
const int N=1000006;
const int M = 1e9+7;
const int inv3 = (M+1)/3;
int ans[N];
map<int,int> mp;
void init(){
for(int i=0;i<N;++i){
ans[i] = LL(i-1)*(i-2)%M;
}
for(int i=1;i<N;++i){ // Pretreatment acceleration
for(int j=i<<1;j<N;j+=i){
ans[j] -= ans[i];
if(ans[j] < 0) ans[j] += M;
}
}
for(int i=2;i<N;++i){
ans[i] += ans[i-1];
if(ans[i] > M) ans[i] -= M;
}
}
int getans(int n){
if(n<N) return ans[n];
map<int,int>::iterator it = mp.find(n); //Memory search
if (it != mp.end()) return it->second;
int r = LL(n)*(n-1)%M*(n-2)%M*inv3%M;
for(int i=2,j;i<=n;i=j+1){
j = n/(n/i);
r -= LL(j-i+1)*getans(n/i)%M;
if(r<0) r+=M;
}
mp.insert(pair<int,int>(n,r));
return r;
}
int main(){
// freopen("/Users/c10110057/Desktop/AC/in","r",stdin);
init();
int T,n;
cin>>T;
while(T--){
scanf("%d",&n);
cout<<getans(n)<<endl;
}
return 0;
}

6. Note

All C++ code above should be changed to fit different demands.Thanks Zimpha who provides some problems and ideas two years old.