Multiplicative function Summary

Pre-defined and Cheese

Arithmetical functions: refers to the domain is a positive integer, the domain of complex function, in OI in the range of functions such vast majority also an integer

Multiplicative function: means for arithmetical function \ (f (x) \) and any pair of mutually prime integers \ (A, B \) , have properties \ (f (ab) = f (a) f (b) \ ) .

Mobius inversion and Dirichlet convolution: a long time ago wrote his own blog

In OI, there is a kind of classic question is evaluating a number theoretic function (or prefix and), it could be like \ (\ mu, \ varphi \ ) such widely-known arithmetical functions, there may be some even complete expressions write function, but they all have one characteristic - they are all multiplicative function. So we can consider some special way they "screen out"

Linear function of the quadrature sieve

Multiplicative function is defined based on the prime, and a prime number is a special case is where a prime number, so we consider when the screen simultaneously primes the calculated value of the product function

Specifically, we recorded \ (low [i] \) represents \ (I \) maximum power minimum quality factor number such that it is still \ (I \) factor, the The wire mesh primes can easily maintenance, the next step is to deal with the current screen number and whether it is prime to prime numbers.

According to the above description is not difficult to find that we really just care about the value of this product of the following functions: \ (f (1), f (the p-) (initial value of prime numbers), f (p ^ k) prime (if used to screen and the screen is not prime number) \) , in fact, of course, a lot of time \ (f (p ^ k) \) values are from \ (f (p ^ {k -1}) \) recursive obtained

Offer some pseudocode

rep(i,2,N)
{
    if (!nopri[i]) {pri[++tot]=i;low[i]=i;f[i]=...(根据定义);}
    int j;
    for (j=1;j<=tot&&i*pri[j]<=N;j++)
    {
        nopri[i*pri[j]]=1;
        if (i%pri[j])
        {
            low[i*pri[j]]=low[i];
            f[i*pri[j]]=f[i]*f[pri[j]];
        }
        else
        {
            low[i*pri[j]]=low[i]*pri[j];
            f[i*pri[j]]=f[i/low[i]]*f[low[i]*pri[j]]\\注意后者可能需要根据定义求得
            break;
        }
    }
}

(Did not try to compile, there may be a problem, please point out!)

Du teach sieve

Linear screen time complexity is clearly \ (O (n) \) , and in many of the issues are already very good time

But the fact is there is always a question of what cancer who write \ (n \ leq 10 ^ 9 \) even more, so we need some practice with better

dls for us to provide a \ (O (n ^ {\ frac {2} {3}}) \) method multiplicative function and prefix to time within

For a multiplicative function \ (F \) , and found two prefixes the sake of convenience multiplicative function \ (g, h \) such that \ (F * G = H \) , then
\ [\ begin {aligned} \ sum_ {i = 1} ^ nf ( i) = & \ sum_ {i = 1} ^ n (h (i) - \ sum_ {d | i, d \ neq i} (f (d) g (\ frac {i } {d})) \\ = & H (n) - \ sum_ {i = 1} ^ n \ sum_ {d | i, d \ neq i} (f (d) g (\ frac {i} {d} )) \\ = & H (n ) - \ sum_ {d = 1} ^ nf (d) \ sum_ {i = 2} ^ {\ lfloor \ frac {n} {d} \ rfloor} g (i) \\ = & H (n) - \ sum_ {i = 2} ^ ng (i) \ sum_ {d = 1} ^ {\ lfloor \ frac {n} {i} \ rfloor} f (i) \\ = & H (n ) - \ sum_ {i = 2
} ^ ng (i) F (\ lfloor \ frac {n} {i} \ rfloor) \ end {aligned} \] used Note that the above derivation capital letters indicate corresponding integrability prefix and function

So we can consider the sieve portion of wire \ (F \) , then use the memory search number theory block Solving the final answer, proved, when the \ (N = n ^ \ frac {2} {3} \ ) when the optimal time for \ (O (n ^ {\ frac {2} {3}}) \)

Example: seeking \ (\ MU \) , \ (\ varphi \) prefix and, \ (n-\ Leq. 9 ^ 10 \)

Consider Du teach sieve, \ (\ * MU the I = \ Epsilon \) , \ (\ varphi = ID_1 the I * \) , you can apply the above derivation

Because too lazy handwritten hash so took unordered_map

#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<vector>
#include<queue>
#include<map>
#include<unordered_map>
using namespace std;
const int maxd=1000000007,N=5000000;
const double pi=acos(-1.0);
typedef long long ll;
int n,mu[5005000],pri[1001000],cnt=0;
ll phi[5005000];
bool ispri[5005000];
unordered_map<int,int> ansmu;
unordered_map<int,ll> ansphi;

int read()
{
    int x=0,f=1;char ch=getchar();
    while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    return x*f;
}

void init()
{
    mu[1]=1;phi[1]=1;
    int i,j;
    for (i=2;i<=N;i++)
    {
        if (!ispri[i]) {pri[++cnt]=i;mu[i]=-1;phi[i]=i-1;}
        for (j=1;j<=cnt && i*pri[j]<=N;j++)
        {
            ispri[i*pri[j]]=1;
            if (i%pri[j]==0) {phi[i*pri[j]]=phi[i]*pri[j];break;}
            else {mu[i*pri[j]]-=mu[i];phi[i*pri[j]]=phi[pri[j]]*phi[i];}
        }
    }
    for (i=1;i<=N;i++) {phi[i]+=phi[i-1];mu[i]+=mu[i-1];}
}

int get_mu(int n)
{
    if (n<=N) return mu[n];
    if (ansmu[n]) return ansmu[n];
    int ans=1;
    unsigned int l,r;
    for (l=2;l<=n;l=r+1)
    {
        r=n/(n/l);
        ans-=(r-l+1)*get_mu(n/l);
    }
    ansmu[n]=ans;
    return ans;
}

ll get_phi(int n)
{
    if (n<=N) return phi[n];
    if (ansphi[n]) return ansphi[n];
    ll ans=((1ll+n)*n)/2ll;
    unsigned int l,r;
    for (l=2;l<=n;l=r+1)
    {
        r=n/(n/l);
        ans-=1ll*(r-l+1)*get_phi(n/l);
    }
    ansphi[n]=ans;
    return ans;
}

void work()
{
    int i,T=read();
    while (T--)
    {
        int n=read();
        ll ans1=get_phi(n);
        int ans2=get_mu(n);
        printf("%lld %d\n",ans1,ans2);
    }
}

int main()
{
    init();
    work();
    return 0;
}

\ (min25 \) screen

Du teach sieve seeking prefix multiplicative function and have been able to do good \ (O (n ^ {\ frac {2} {3}}) \) , but still has a big drawback: we have to find two a facilitating seeking prefix and a multiplicative function \ (g, h \) such that they are multiplicative function are asking \ (F \) has (f * g = h \) \ relationship, which in some conventional multiplicative function relatively common, but in some people the cancer out of the equation given in the question can not be found (some do not even give you a full function definition equation), this time we have to look back to the wire began sieve, and there is no better thing to do?

\ (min25 \) proposes a multiplicative function sieve may \ (O (\ frac {n ^ {0.75}} {log \ n}) \) is determined within a multiplicative function of time and the prefix (but I will not permit this complexity, another widely circulated time complexity is \ (O (n ^ {1- \ epsilon}) \)

\ (min25 \) are the following two steps
(1) \ (\ FORALL \ X = \ lfloor \ {n-FRAC {I}} \ rfloor \) , seeking \ (\ sum_ {i = 1 } ^ x [ I \ in P] I ^ K \) , wherein uppercase \ (P \) represents the set of prime numbers, \ (K \) is a constant whose value is often based on the question in the form of a function (primarily \ (F (the p-^ k) \) ) is determined, sometimes \ (k \) the value will be more than one

We remember \ (G (n-, J) = \ sum_ {I =. 1} ^ n-[I \ in P \ or \ min (I) \ GEQ p_j] I ^ K \) , where \ (min (i) \ ) represents \ (I \) minimum quality factor, \ (p_j \) represents the \ (J \) prime numbers, it is clear that we have at this step the final requirement is \ (\ forall \ x = \ lfloor \ frac {n } {i} \ rfloor, g (x, | P |) \) values

How to get \ (g \) the value of it? We consider it practical significance, let us return to an old sieve method prime - Eppendorf sieve method, it is considered to select the smallest number is not currently being screened out, and finds that it is a prime number, and use it to screen out of the remaining number is a multiple of the number of primes. We found \ (g (n, j) \) is in use \ (j \) after leaving Egypt were a prime number sieve \ (f \) value

According to the current \ (j \) to classify the discussion of values

i) If the \ (p_j \ Leq \ n-sqrt {} \) , then we will be screened out that a minimum quality factor is exactly \ (p_j \) number, that is, removal of a \ (p_j \) after the remaining number of the minimum prime factors must be greater than equal to \ (p_j \) , i.e. \ (g (\ lfloor \ frac {n} {p_j} \ rfloor, j-1) - \ sum_ {i = 1} ^ { j-1} f (p_i) \)

ii) if \ (p_j> \ sqrt {n-} \) , then this time screened out number is at least \ (p_j ^ 2 \) , which is greater than \ (n-\) number, so that once the screen is not will change the number to the left, that is, \ (g (n, j- 1) \)

In summary, there are
\ [g (n, j) = \ begin {cases} g (n, j-1) & p_j> \ sqrt {n} \\ g (n, j-1) -f (p_j ) [g (\ lfloor \ frac {n} {p_j} \ rfloor, j-1) - \ sum_ {i = 1} ^ {j-1} f (p_i)] & p_j \ leq \ sqrt {n} \ end {cases} \]
Therefore, we can directly screen \ (\ sqrt {n} \ ) primes less than, then recursion give \ (g (n, | P |) \) to

(2) find \ (S (n, j)
= \ sum_ {i = 1} ^ n [min (i) \ geq p_j] f (i) \) then obviously \ (\ sum_ {i = 1 } ^ nf (i) = S (n
, 1) + f (1) \) seeking \ (S (n, j) \) then consider two parts, a prime number, when subtracted directly \ (<p_j \) of can prime number, this part is \ (g (n, j) - \ sum_ {i = 1} ^ {j-1} f (p_i) \)

Next, consider a composite number, a note number satisfying the condition must be written \ (p_k ^ e * x \ ) form (where \ (min (X) \ GEQ P_K \) ), so we can enumerate \ (K \) and \ (E \) , counted separately \ (X \) whether there are \ (P_K \) can be
written together is
\ [S (n, j) = g (n, j) - \ sum_ { i = 1} ^ {j- 1} f (p_i) + \ sum_ {k = j} ^ {p_k ^ 2 \ leq n} \ sum_ {e = 1} ^ {p ^ {e + 1} \ leq n } (S (\ frac {n } {p_k ^ e}, k + 1) f (p_k ^ e) + f (p_k ^ {e + 1})) \]

Boundary condition is that \ (n \ leq 0 \) or \ (p_j> n \) when \ (S (n, j) = 0 \)

Example: DIVCNT2

Du said to be vigorously teach sieve. . . IQ is too low not to feel Assembly

Spoj official website to look at this question, then found data unit is relatively capital porcelain min25 sieve, so he wrote out of min25

First, it is easy to multiplicative function card, and secondly there \ (F (. 1) =. 1, F (P) =. 3, F (K ^ P). 1 = 2K + \) , where since \ (F ( P) \) and \ (f (p ^ k) \) are the \ (P \) independent, so we determined directly \ (\ sum_ {i = 1 } ^ {\ lfloor \ frac {n} {j} \ rfloor} [i \ in P] \) to

Constant codes offer huge

#pragma GCC optimize(2)
#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
typedef unsigned long long ull;
const int N=2000000;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define fir first
#define sec second
#define mp(a,b) make_pair(a,b)
#define pb(a) push_back(a)
#define maxd 998244353
#define eps 1e-8
int m,ptot=0,id1[N+10],id2[N+10],tot=0,pri[N+10];
ll n,w[N+10];
bool nopri[N+10];
ull g[N+10];

ll read()
{
    ll x=0;int f=1;char ch=getchar();
    while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    return x*f;
}

void sieve()
{
    rep(i,2,N)
    {
        if (!nopri[i]) pri[++ptot]=i;
        int j;
        for (j=1;j<=ptot && i*pri[j]<=N;j++)
        {
            nopri[i*pri[j]]=1;
            if (i%pri[j]==0) break;
        }
    }
}

void calc(ll n)
{
    m=sqrt(n);tot=0;
    ll l,r;
    for (l=1;l<=n;l=r+1)
    {
        r=n/(n/l);w[++tot]=(n/l);
        if (w[tot]<=m) id1[w[tot]]=tot;else id2[n/w[tot]]=tot;
        g[tot]=w[tot]-1;
    }
    int i,j;
    for (i=1;i<=ptot && 1ll*pri[i]*pri[i]<=n;i++)
    {
        for (j=1;j<=tot && 1ll*pri[i]*pri[i]<=w[j];j++)
        {
            int k;
            if (w[j]/pri[i]<=m) k=id1[w[j]/pri[i]];else k=id2[n/(w[j]/pri[i])];
            g[j]=g[j]-g[k]+(i-1);
        }
    }
}

ull s(ll lim,int cnt)
{
    if ((lim<=1) || (pri[cnt]>lim)) return 0;
    ull ans=0;
    if (lim<=m) ans=3ull*(g[id1[lim]]-(cnt-1));else ans=3ull*(g[id2[n/lim]]-(cnt-1));
    int i,j;
    for (i=cnt;i<=ptot&&1ll*pri[i]*pri[i]<=lim;i++)
    {
        ll pro=pri[i];
        for (j=1;pro*pri[i]<=lim;j++,pro=pro*pri[i])
        {
            ans+=s(lim/pro,i+1)*(j*2+1)+j*2+3;
        }
    }
    return ans;
}

signed main()
{
    sieve();
    int T=read();
    while (T--)
    {
        n=read();
        calc(n);
        printf("%llu\n",s(n,1)+1);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/encodetalker/p/11129927.html