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; }
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; }
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; }
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; }
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; }