1. 程式人生 > >icpc預賽徐州: Easy Math (有關莫比烏斯函式的數學難題)

icpc預賽徐州: Easy Math (有關莫比烏斯函式的數學難題)

題意:

i=1mu(in)

解析:

如果n有個因子是某個素數的平方,那麼根據莫比烏斯函式,答案為0,所以我們考慮其他的情況

設d為n的一個素因子,那麼n/d與d互質,而莫比烏斯函式又是積性函式,所以有:

i=1mu(in)=i=1mu(idnd)=i=1mu(ind)u(d)

而質數的函式值為-1,所以原式變成:

i=1mu(ind)

但是我們好像漏了一個東西,d和n/d互質,但是隻有當d和i也互質的時候才能拆出來,而不能拆出來的部分有哪些呢?d為質數,所以i為d的倍數的時候才不互質,所以答案為:

i[1,m]diu(ind)u(d)+i[1,m]diu(indd)

顯然右邊部分為0,答案為:

i=1mu(ind)+i[1,m]diu(ind)=i=1mu(ind)+i=1m/du(in)

為什麼後半部分可以把1/d提到前面去呢?因為後半部分的i本來就只能取d的倍數,而前半部分i範圍為1到m,換成1到m/d後就少了很多

接下來令原答案為Ans(n,m),則有:

Ans(n,m)=Ans(n/d,m)+Ans(n,m/d)

遞迴到最後Ans(n,0)顯然是0,而Ans(1,m),在n=1時已經取不到d了就不能往下分了,也就是說需要計算以下公式:

Ans(1,m)=i=1mu(i)這個其實裸杜教篩就可以了。

程式碼:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int N=10000111;
#define pill pair<LL ,LL>
int
u[N]; LL pre[N]; LL pri[N>>1],now; bool vis[N]; void init(){ u[1]=1;now=0; for(LL i=2;i<N-9;i++){ if(!vis[i]){ pri[++now]=i;u[i]=-1; } for(int j=1;j<=now&&i*pri[j]<N-9;j++){ vis[i*pri[j]]=1; u[i*pri[j]]=-u[i]; if(i%pri[j]==0){ u[i*pri[j]]=0; break; } } } pre[0]=0; for(int i=1;i<N-9;i++)pre[i]=u[i]+pre[i-1]; } unordered_map<LL,LL>M; LL calculate(LL n){//杜教篩 if(M.find(n)!=M.end())return M[n]; if(n<N-9)return pre[n]; LL ans=1; for(LL l=2,r;l<=n;l=r+1){ r=n/(n/l); ans-=(r-l+1ll)*calculate(n/l); } return M[n]=ans; } bool judge(LL n){//判斷u(n)是否直接=0 for(int i=1;pri[i]*pri[i]<=n;i++){ if(n%pri[i])continue; n/=pri[i]; if(n%pri[i]==0)return false; } return true; } LL Ans(LL n,LL m){ if(n==1)return calculate(m); if(m==0)return 0; if(!judge(n))return 0; LL d=-1; //之前定義為int RE了一上午,氣死了 for(int i=1;pri[i]*pri[i]<=n;i++) if(n%pri[i]==0){d=pri[i];break;} if(d==-1)d=n; return Ans(n,m/d)-Ans(n/d,m); } int main(){ init(); LL m,n; cin>>m>>n; if(!judge(n))return 0*printf("0\n"); return 0*printf("%lld\n",Ans(n,m)); }