# 一类积性函数的前缀和---刷题记录

### 51Nod 1244 莫比乌斯函数之和

$f(n)=\sum _{i=1}^{n}$

$1=\sum _{i=1}^{n} [i==1]$

$=\sum _{i=1}^{n} \sum _{d\mid i} \mu (d)$

$=\sum _{\frac{i}{d}=1}^{n} \sum _{d=1}^{\frac{n}{\frac{i}{d}}} \mu (d)$

$=\sum _{i=1}^{n}\sum _{d=1}^{\frac{n}{i}} \mu(d)$

$=\sum _{i=1}^{n}f(\frac{n}{i})$

$f(n)=1-\sum _{i=2}^{n} f(\frac{n}{i})$

#### 代码：

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
//by NeighThorn
using namespace std;

const int maxn=5000000+5;

int cnt,mu[maxn],pri[maxn],vis[maxn];
long long n,m,f[maxn];

map<long long,long long> mp;

inline void prework(void){
mu[1]=1;
for(int i=2;i<=5000000;i++){
if(!vis[i])
vis[i]=1,pri[++cnt]=i,mu[i]=-1;
for(int j=1;j<=cnt&&1LL*i*pri[j]<=5000000;j++){
vis[i*pri[j]]=1;
if(i%pri[j]==0){
mu[i*pri[j]]=0;
break;
}
mu[i*pri[j]]=-mu[i];
}
}
for(int i=1;i<=5000000;i++) f[i]=f[i-1]+mu[i];
}

inline long long calc(long long x){
if(x<=5000000) return f[x];
if(mp.find(x)!=mp.end()) return mp[x];
long long ans=1;
for(long long i=2,r;i<=x;i=r+1){
r=x/(x/i);
ans-=calc(x/i)*(r-i+1);
}
return mp[x]=ans;
}

signed main(void){
prework();scanf("%lld%lld",&n,&m);
printf("%lld\n",calc(m)-calc(n-1));
return 0;
}


### 51Nod 1239 欧拉函数之和

$\phi(n)=n-\sum _{d\mid n d<n}\phi(d)$

$f(n)=\sum _{i=1}^{n} (i-\sum _{d\mid i d<i} \phi(d))$

$=\frac{n(n+1)}{2}-\sum _{i=2}^{n} \sum _{d\mid i d<i} \phi(d)$

$=\frac{n(n+1)}{2}-\sum _{i=2}^{n}\sum _{d=1}^{\frac{n}{i}} \phi(d)$

$=\frac{n(n+1)}{2}-\sum _{i=2}^{n} f(\frac{n}{i})$

#### 代码：

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
//by NeighThorn
using namespace std;

const int maxn=5000000+5,mod=1e9+7;

int cnt,f[maxn],pri[maxn],phi[maxn],vis[maxn];
long long n;

map<long long,int> mp;

inline int mul(long long x,long long y){
int res=0;x%=mod;
while(y){
if(y&1) res=(res+x)%mod;
x=(x+x)%mod,y>>=1;
}
return res;
}

inline int power(int x,int y){
int res=1;
while(y){
if(y&1) res=1LL*res*x%mod;
x=1LL*x*x%mod,y>>=1;
}
return res;
}

inline void prework(void){
phi[1]=1;
for(int i=2;i<=5000000;i++){
if(!vis[i])
pri[++cnt]=i,vis[i]=1,phi[i]=i-1;
for(int j=1;j<=cnt&&1LL*i*pri[j]<=5000000;j++){
vis[i*pri[j]]=1;
if(i%pri[j]==0){
phi[i*pri[j]]=phi[i]*pri[j];
break;
}
phi[i*pri[j]]=phi[i]*(pri[j]-1);
}
}
for(int i=1;i<=5000000;i++) f[i]=(f[i-1]+phi[i])%mod;
}

inline int calc(long long n){
if(n<=5000000) return f[n];
if(mp.find(n)!=mp.end()) return mp[n];
int ans=mul(mul(n,n+1),power(2,mod-2));
for(long long i=2,r;i<=n;i=r+1){
r=n/(n/i);
ans=(ans-1LL*calc(n/i)*((r-i+1)%mod)%mod+mod)%mod;
}
return mp[n]=ans;
}

signed main(void){
prework();scanf("%lld",&n);
printf("%lld\n",calc(n));
return 0;
}


### 51Nod 1190 最小公倍数之和 V2

推了好久的式子发现本来还挺对的，后来越来越麻烦...一定是化简方向错了...所以看了题解...发现果然如此...

if(1LL*pri[i]*pri[i]>tmp) break;


#### 代码：

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
//by NeighThorn
using namespace std;

const int maxn=100000+5,mod=1e9+7;

int n,m,ans,cas,cnt,inv,tot,tot_pri,pri[maxn],exp[maxn],vis[maxn],fact[maxn],fac_pri[maxn];

inline int power(int x,int y){
int res=1;
while(y){
if(y&1)
res=1LL*res*x%mod;
x=1LL*x*x%mod,y>>=1;
}
return res;
}

inline void prework(void){
for(int i=2;i<=100000;i++){
if(!vis[i])
vis[i]=1,pri[++cnt]=i;
for(int j=1;j<=cnt&&1LL*i*pri[j]<=100000;j++){
vis[i*pri[j]]=1;
if(i%pri[j]==0) break;
}
}
}

inline void dfs(int id,int fac){
if(id>tot_pri){
fact[++tot]=fac;return;
}
dfs(id+1,fac);
for(int i=1;i<=exp[id];i++)
fac*=fac_pri[id],dfs(id+1,fac);
}

inline void getfact(void){
int tmp=m;
for(int i=1;i<=cnt;i++){
if(1LL*pri[i]*pri[i]>tmp) break;
if(tmp%pri[i]==0){
fac_pri[++tot_pri]=pri[i],exp[tot_pri]=0;
while(tmp%pri[i]==0)
exp[tot_pri]++,tmp/=pri[i];
}
}
if(tmp>1) fac_pri[++tot_pri]=tmp,exp[tot_pri]=1;
dfs(1,1);
}

signed main(void){
//	freopen("51nod_Problem_1190_Test_16_In.txt","r",stdin);
//	freopen("out.txt","w",stdout);
scanf("%d",&cas);prework();inv=power(2,mod-2);
while(cas--){
scanf("%d%d",&n,&m);
tot_pri=tot=ans=0;getfact();
for(int i=1,tmp,ttmp,lala;i<=tot;i++){
tmp=1;ttmp=n+fact[i]-1;lala=fact[i];
for(int j=1;j<=tot_pri;j++)
if(fact[i]%fac_pri[j]==0)
tmp=1LL*tmp*(1-fac_pri[j]+mod)%mod;
tmp=1LL*tmp*inv%mod;
tmp=1LL*tmp*((ttmp/lala+m/lala)%mod)%mod;
tmp=1LL*tmp*(m/lala-ttmp/lala+1)%mod;
ans=(ans+tmp)%mod;
}
ans=1LL*ans*m%mod;
printf("%d\n",ans);
}
return 0;
}


### BZOJ 3944: Sum

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
//by NeighThorn
using namespace std;

const int maxn=5000000+5;

bool vis[maxn];
int n,cas,cnt,pri[maxn/5];
long long f1[maxn],f2[maxn];

map<int,long long> mp1,mp2;

inline void prework(void){
f2[1]=f1[1]=1;
for(int i=2;i<=5000000;i++){
if(!vis[i])
vis[i]=1,pri[++cnt]=i,f2[i]=-1,f1[i]=i-1;
for(int j=1;j<=cnt&&1LL*i*pri[j]<=5000000;j++){
vis[i*pri[j]]=1;
if(i%pri[j]==0){
f2[i*pri[j]]=0;
f1[i*pri[j]]=f1[i]*pri[j];
break;
}
f1[i*pri[j]]=f1[i]*(pri[j]-1),f2[i*pri[j]]=-f2[i];
}
}
for(int i=1;i<=5000000;i++) f1[i]+=f1[i-1],f2[i]+=f2[i-1];
}

inline long long calc1(long long n){
if(n<=5000000) return f1[n];
if(mp1.find(n)!=mp1.end()) return mp1[n];
long long ans=1LL*n*(n+1)/2;
for(long long i=2,r;i<=n;i=r+1){
r=n/(n/i);
ans-=(r-i+1)*calc1(n/i);
}
return mp1[n]=ans;
}

inline long long calc2(long long n){
if(n<=5000000) return f2[n];
if(mp2.find(n)!=mp2.end()) return mp2[n];
long long ans=1;
for(long long i=2,r;i<=n;i=r+1){
r=n/(n/i);
ans-=(r-i+1)*calc2(n/i);
}
return mp2[n]=ans;
}

signed main(void){
scanf("%d",&cas);prework();
while(cas--){
scanf("%d",&n);
printf("%lld %lld\n",calc1(n),calc2(n));
}
return 0;
}


HDU 5608 Function

$\sum _{i=1}^{n} \sum _{d\mid i} f(d)$

$=\sum _{i=1}^{n} f(i)\left \lfloor \frac{n}{i} \right \rfloor$

$=\sum _{i=1}^{n} g(\left \lfloor \frac{n}{i} \right \rfloor)$

$\sum _{d\mid n}f(d)=F(n)$

$f(n)=\sum _{d\mid n} \mu(d) F(\frac{n}{d})$

#### 代码：

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
//by NeighThorn
using namespace std;

const int mod=1e9+7,maxn=1000000+5;

int n,cas,cnt,inv,f[maxn],mu[maxn],pri[maxn],vis[maxn];
map<int,int> mp;

inline int power(int x,int y){
int res=1;
while(y){
if(y&1)
res=1LL*res*x%mod;
x=1LL*x*x%mod,y>>=1;
}
return res;
}

inline int F(int x){
return 1LL*(x-1)*(x-2)%mod;
}

inline void prework(void){
mu[1]=1;
for(int i=2;i<=1000000;i++){
if(!vis[i])
vis[i]=1,pri[++cnt]=i,mu[i]=-1;
for(int j=1;j<=cnt&&1LL*i*pri[j]<=1000000;j++){
vis[i*pri[j]]=1;
if(i%pri[j]==0){
mu[i*pri[j]]=0;
break;
}
mu[i*pri[j]]=-mu[i];
}
}
for(int i=1;i<=1000000;i++)
for(int j=i;j<=1000000;j+=i){
f[j]+=mu[i]*F(j/i);
if(f[j]<0) f[j]+=mod;
f[j]%=mod;
}
for(int i=1;i<=1000000;i++) f[i]=(f[i]+f[i-1])%mod;
}

inline int calc(int n){
if(n<=1000000) return f[n];
if(mp.find(n)!=mp.end()) return mp[n];
int ans=1LL*n*(n-1)%mod*(n-2)%mod*inv%mod;
for(int i=2,r;i<=n;i=r+1){
r=n/(n/i);
ans=ans-1LL*(r-i+1)*calc(n/i)%mod;
if(ans<0) ans+=mod;
ans%=mod;
}
return mp[n]=ans;
}

signed main(void){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
scanf("%d",&cas);inv=power(3,mod-2);prework();
while(cas--){
scanf("%d",&n);
printf("%d\n",calc(n));
}
return 0;
}


### 51Nod 1238 最小公倍数之和 V3

$\sum _{i=1}^{n} \sum _{j=1}^{m} lcm(i,j)$

$=\sum _{i=1}^{n} \sum _{j=1}^{m} \frac {i*j}{gcd(i,j)}$

$=\sum _{d=1}^{n} d \sum _{i=1}^{\frac{n}{d}} \sum _{j=1}^{\frac{m}{d}} i*j*[gcd(i,j)==1]$

$=\sum _{d=1}^{n} d \sum _{i=1}^{\frac{n}{d}} i \sum _{j=1}^{\frac{m}{d}} j*[gcd(i,j)==1]$

$\sum _{i=1}^{n} i*[gcd(i,n)==1]=\frac{n\phi(n)}{2}$

$\sum _{d=1}^{n} \sum _{i=1}^{\frac{n}{d}} i*i*\phi(i)$

$\sum _{i=1}^{n} \sum _{d\mid i} \phi(d) i^2=\frac{n^2(n+1)^2}{4}$

$=\sum _{i=1}^{n} \sum _{d\mid i} f(d)(\frac{i}{d})^2$

$=\sum _{i=1}^{n} \sum _{d=1}^{\frac{n}{i}} f(d)i^2$

$Sum(n)=\frac{n^2(n+1)^2}{4}-\sum _{i=2}^{n} i^2Sum(\left \lfloor \frac{n}{i} \right \rfloor$

#### 代码：

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
//by NeighThorn
using namespace std;

const int mod=1e9+7,maxn=5000000+5;

int cnt,inv,inv2,f[maxn],phi[maxn],pri[maxn],vis[maxn];
long long n;

map<long long,int> mp;

inline int power(int x,int y){
int res=1;
while(y){
if(y&1) res=1LL*res*x%mod;
x=1LL*x*x%mod,y>>=1;
}
return res;
}

inline void prework(void){
phi[1]=1;
for(int i=2;i<=5000000;i++){
if(!vis[i])
vis[i]=1,pri[++cnt]=i,phi[i]=i-1;
for(int j=1;j<=cnt&&i*pri[j]<=5000000;j++){
vis[i*pri[j]]=1;
if(i%pri[j]==0){
phi[i*pri[j]]=phi[i]*pri[j];
break;
}
phi[i*pri[j]]=phi[i]*(pri[j]-1);
}
}
for(int i=1;i<=5000000;i++) f[i]=1LL*i*i%mod*phi[i]%mod;
for(int i=1;i<=5000000;i++) f[i]=(f[i]+f[i-1])%mod;
}

inline int calc(long long n){
if(n<=5000000) return f[n];
if(mp.find(n)!=mp.end()) return mp[n];
int ans,tmp;tmp=n%mod;ans=1LL*tmp*(tmp+1)%mod*inv2%mod;ans=1LL*ans*ans%mod;
for(long long i=2,r,x,y;i<=n;i=r+1){
r=n/(n/i);x=(i-1)%mod,y=r%mod;
tmp=1LL*y*(y+1)%mod*(y<<1|1)%mod*inv%mod;
tmp-=1LL*x*(x+1)%mod*(x<<1|1)%mod*inv%mod;
if(tmp<0) tmp+=mod;
ans=(ans-1LL*tmp*calc(n/i)%mod);
if(ans<0) ans+=mod;
}
return mp[n]=ans;
}

signed main(void){
scanf("%lld",&n);prework();
int ans=0;inv=power(6,mod-2),inv2=power(2,mod-2);
for(long long i=1,r,x;i<=n;i=r+1){
r=n/(n/i);x=(n/i)%mod;
ans=(ans+1LL*x*(x+1)%mod*inv2%mod*(calc(r)-calc(i-1)+mod)%mod)%mod;
}
printf("%d\n",ans);
return 0;
}


By NeighThorn

posted @ 2017-04-09 09:07  NeighThorn  阅读(854)  评论(9编辑  收藏  举报