Mobius inversion / linear sieve / multiplicative function / Du teach sieve / min25 screening study notes

Recently re-learned systematically under these knowledge points, we did not find their contact before, this summary.

 

Mobius inversion entry: https://blog.csdn.net/litble/article/details/72804050

Linear sieve and common multiplicative function codes: https://blog.masterliu.net/algorithm/sieve/

Linear multiplicative function screen (including ordinary linear function): https://blog.csdn.net/weixin_42562050/article/details/87997582

 

bzoj2154 / bzoj2693 / Luo Gu P1829 Crash digital form

 This question is seeking   finalizing the formula is such that 

 

 

 So the main contradiction is how demand back that lump, to a deep understanding of linear sieve, and then analyze i% pime [j] == 0 when the prime [j] of new contributions and i% prime [j]! = 0 when the prime [j] contribution.

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e7+10;
const int MOD=1e8+9;
int n,m;

bool vis[N];
int tot=0,pri[N],f[N],s[N];
void prework(int n) {
    f[1]=1;
    for (int i=2;i<=n;i++) {
        if (!vis[i]) pri[++tot]=i,f[i]=(1-i+MOD)%MOD;
        for (int j=1;j<=tot&&i*pri[j]<=n;j++) {
            int k=i*pri[j]; vis[k]=1;
            if (i%pri[j]) f[k]=(LL)f[i]*f[pri[j]]%MOD;
            else { f[k]=f[i]; break; }
        }
    }
    for (int i=1;i<=n;i++) f[i]=(f[i-1]+(LL)i*f[i]%MOD)%MOD;
    for (int i=1;i<=n;i++) s[i]=((LL)i*(i+1)/2)%MOD;
}

int main()
{
    int T; cin>>T;
    prework(10000000);
    while (T--) {
        scanf("%d%d",&n,&m);
        if (n>m) swap(n,m);
        LL ans=0;
        for (int i=1,j;i<=n;i=j+1) {
            j=min(n/(n/i),m/(m/i));
            LL tmp=(LL)s[n/i]*s[m/i]%MOD*(f[j]-f[i-1]+MOD)%MOD;
            ans=(ans+tmp)%MOD;        
        }
        printf("%lld\n",ans);
    }
    return 0;
}
View Code

 

bzoj3994 / Los divisor number and valleys P3327

 Requirements  must be met before until a conclusion can be simplified down

Simplification result is:   which

 

 Then we find that g (x) is actually a prefix D (x) (x is a divisor of the number) and, g (n) = sigma (d (x)) (x = 1 ~ n). 

After then seek prefix linear sieve and, directly to block.

#include <bits / STDC ++ H.>
 the using  namespace STD; 
typedef Long  Long LL;
 const  int N = 5E4 + 10 ;
 int n-, m; 

BOOL VIS [N]; 
LL TOT = 0 , PRI [N], MINP [N] , D [N], U [N];
 void prework ( int n-) {   // linear function of the number of screens required number Mobius about 
    D [ . 1 ] = . 1 ; U [ . 1 ] = . 1 ;
     for ( int I = 2 ; I <= n-; I ++ ) {
         IF (VIS [I]) PRI [TOT ++] = I, MINP [I] =!1,d[i]=2,u[i]=-1;
        for (int j=1;j<=tot&&i*pri[j]<=n;j++) {
            int k=i*pri[j]; vis[k]=1;
            if (i%pri[j]==0) {
                u[k]=0;
                minp[k]=minp[i]+1;
                d[k]=d[i]/(minp[i]+1)*(minp[i]+2);
                break;
            }
            u[k]=-u[i];
            minp[k]=1;
            d[k]=d[i]*2;
        }
    }
    for (int i=1;i<=n;i++) d[i]+=d[i-1],u[i]+=u[i-1];
}

int main()
{
    prework(50000);
    int T; cin>>T;
    while (T--) {
        scanf("%d%d",&n,&m);
        if (n>m) swap(n,m);
        LL ans=0;
        for (int i=1,j;i<=n;i=j+1) {
            j=min(n/(n/i),m/(m/i));
            ans+=(LL)d[n/i]*d[m/i]*(u[j]-u[i-1]);
        }
        printf("%lld\n",ans);
    }
    return 0;
}
View Code

 

bzoj3529 / Luo Gu number P3312 table

 Claim  (wherein [sigma] (x) and the number x represents approximately), which is reduced to give the formula

 

 

 Cook stuff is noted that the latter can be a linear convolution Dealy Cray screen, but this question asked a plurality of sets (n, m, a), this effect is a limit σ (x)> a not contribute. In this case the screen can not without brain prefix and then block the direct calculation.

So we consider off-line, to ask of a small to large order. So for the time a query, we added one by one σ (x) <= a contribution of σ (x) for the answer, then we block this time is the correct calculation of the contribution. Then they would need for a section and can be inserted into the values ​​of the data structure of the query, BIT is such a data structure and a smaller constant. Each addition a [sigma] (x) for multiple updates we consider all of x σ (x) * μ (T / d). Update the time complexity is n / 1 + n / 2 + ... n / n = nlogn infinite series is not time out.

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+10;
int n,m,ans[N];
struct dat{
    int n,m,a,id;
    bool operator < (const dat &rhs) const {
        return a<rhs.a;
    }
}Q[N];
struct sumdat{
    int id,sum;
    bool operator < (const sumdat &rhs) const {
        return sum<rhs.sum;
    }
}d[N];

bool vis[N];
int tot=0,pri[N],u[N],minp[N],sump[N];
void prework(int n) {
    u[1]=1; minp[1]=1; sump[1]=1;
    for (int i=2;i<=n;i++) {
        if (!vis[i]) pri[++tot]=i,minp[i]=i,sump[i]=i+1,u[i]=-1;
        for (int j=1;j<=tot&&i*pri[j]<=n;j++) {
            int k=i*pri[j]; vis[k]=1;
            if (i%pri[j]==0) {
                u[k]=0;            
                minp[k]=minp[i]*pri[j];
                LL tmp=(LL)sump[i]*((LL)minp[k]*pri[j]-1);
                sump[k]=(int)(tmp/(minp[k]-1));
                break;    
            }
            u[k]=-u[i];
            minp[k]=pri[j];
            sump[k]=sump[i]*(1+pri[j]);
        }
    }
    for (int i=1;i<=n;i++) d[i].id=i,d[i].sum=sump[i];
}

int sum[N];
void update(int x,int v) {
    for (;x<=100000;x+=x&-x) sum[x]+=v;
}
int query(int x) {
    int ret=0;
    for (;x;x-=x&-x) ret+=sum[x];
    return ret;
}

int solve(int n,int m) {
    if (n>m) swap(n,m);
    int ret=0;
    for (int i=1,j;i<=n;i=j+1) {
        j=min(n/(n/i),m/(m/i));
        ret+=(n/i)*(m/i)*(query(j)-query(i-1));
    }
    return ret;
}

int main()
{
    prework(100000);
    int T; cin>>T;
    for (int i=1;i<=T;i++) {
        scanf("%d%d%d",&Q[i].n,&Q[i].m,&Q[i].a);
        Q[i].id=i;
    }
    sort(Q+1,Q+T+1);
    sort(d+1,d+100000+1);
    int now=1;
    for (int i=1;i<=T;i++) {
        while (now<=100000 && d[now].sum<=Q[i].a) {
            for (int i=d[now].id;i<=100000;i+=d[now].id)
                update(i,d[now].sum*u[i/d[now].id]);
            now++;
        }
        ans[Q[i].id]=solve(Q[i].n,Q[i].m);
    }
    for (int i=1;i<=T;i++) {
        if (ans[i]<0) ans[i]+=2147483647,ans[i]++;
        printf("%d\n",ans[i]);
    }
    return 0;
} 
View Code

 

Luo Gu P3768 simple math problems

 

Du teach sieve

Mobius function given prefix and demand and the Euler function and prefix template. (Because of the use map, will be submitted to the OJ TLE)

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=3e6+10;
const int Pr=3e6;
unordered_map<LL,LL> mm,mp;

bool vis[N];
int tot=0,pri[N]; LL mu[N],phi[N];
void prework() {
    vis[1]=1; mu[1]=phi[1]=1;
    for (int i=2;i<=Pr;i++) {
        if (!vis[i]) pri[++tot]=i,mu[i]=-1,phi[i]=i-1;
        for (int j=1;j<=tot&&i*pri[j]<=Pr;j++) {
            int k=i*pri[j]; vis[k]=1;
            if (i%pri[j]==0) {
                mu[k]=0; phi[k]=phi[i]*pri[j];
                break;
            }
            mu[k]=-mu[i]; phi[k]=phi[i]*phi[pri[j]];
        }
    }
    for (int i=1;i<=Pr;i++) mu[i]+=mu[i-1];
    for (int i=1;i<=Pr;i++) phi[i]+=phi[i-1];
}

LL getmu(LL n) {
    if (n<=Pr) return mu[n];
    if (mm.count(n)) return mm[n];
    LL ret=0,i=2,j;
    while (i<=n) {
        j=n/(n/i);
        ret+=(j-i+1)*getmu(n/i);
        i=j+1;
    }
    returnmm [n-] = . 1 - RET; 
} 

LL getphi (n-LL) { 
    IF (n-<= Pr) return Phi [n-];   // pretreated 
    IF (mp.count (n-)) return MP [n-];   // counted the 
    LL RET = 0 , I = 2 , J;
     the while (I <= n-) {   // number Theory block determined later cook 
        J = n-/ (n-/ I); 
        RET + = (J- + I . 1 ) getphi * (n-/ I); 
        I = J + . 1 ; 
    } 
    return MP [n-] = n-* (n-+ . 1 ) / 2 -  RET;
}

int main()
{
    prework();
    int T; cin>>T;
    while (T--) {
        LL n; scanf("%lld",&n);
        printf("%lld %lld\n",getphi(n),getmu(n));
    }
    return 0;
}
View Code

 

BZOJ-4916

The main demand is phi (i ^ 2) prefix and, f (i) = phi (i ^ 2) = i * phi (i). Configured as a way to g (i) and f (i) do Dealy Cray convolution result sake of convenience.

So sigma f (i) * g (n / i) = sigma i * phi (i) * g (n / i), we also know that sigma (phi (i)) (i | n) = n then g What is make it simple formula? The idea is to pure expression of this i disappear, then g (i) = i on the line.

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e7+10;
const int Pr=1e7;
const int MOD=1e9+7;
const int inv=166666668;  //6的逆元 
map<LL,LL> mp;

bool vis[N];
int tot=0,pri[N]; LL mu[N],phi[N];
void prework() {
    vis[1]=1; mu[1]=phi[1]=1;
    for (int i=2;i<=Pr;i++) {
        if (!vis[i]) pri[++tot]=i,mu[i]=-1,phi[i]=i-1;
        for (int j=1;j<=tot&&i*pri[j]<=Pr;j++) {
            int k=i*pri[j]; vis[k]=1;
            if (i%pri[j]==0) {
                mu[k]=0; phi[k]=phi[i]*pri[j]%MOD;
                break;
            }
            mu[k]=-mu[i]; phi[k]=phi[i]*phi[pri[j]]%MOD;
        }
    }
    for (int i=1;i<=Pr;i++) phi[i]=phi[i]*i%MOD;
    for (int i=1;i<=Pr;i++) phi[i]+=phi[i-1],phi[i]%=MOD;
}

LL solve(LL n) {
    if (n<=Pr) return phi[n];
    if (mp.count(n)) return mp[n];
    LL ret=0,i=2,j;
    while (i<=n) {
        j=n/(n/i);
        entitled + = (i + j) * (j-i + 1 ) / 2 % v * solve (n / i)% V; 
        entitled % = v; 
        in = j + 1 ; 
    } 
    Right = n * (n + 1 ) v% * ( 2 * n + 1 ) *% v inv% MOD right; 
    right = (Right% v + v)% V;
    Return MP [n] = right; 
} 

Int main () 
{ 
    prework (); 
    LL n; cin >> n; 
    printf ( " % lld \ n% lld \ n " , 1 , solve (n));
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/clno1/p/11516737.html