51nod1222 最小公倍數計數
阿新 • • 發佈:2017-06-18
++ esp text put clas -i inpu ret 上界
Input
$$\sum_{d=1}^{n} \sum_{i=1}^{\frac{n}{d}} \sum_{j=1}^{\frac{n}{d}} [i*j<=\frac{n}{d}] [gcd(i,j)==1]$$
$$\sum_{d=1}^{n} \sum_{k=1}^{\frac{n}{d}} \mu(k) \sum_{i=1}^{\frac{n}{d}} \sum_{j=1}^{\frac{n}{d}} [i*k*j*k<=\frac{n}{d}] $$
$$\sum_{k=1}^{n} \mu(k) \sum_{d=1}^{\frac{n}{k}} \sum_{i=1}^{\frac{n}{dk}} \sum_{j=1}^{\frac{n}{dk}} [i*j*d<=\frac{n}{k^2}] $$
題目來源: Project Euler 基準時間限制:6 秒 空間限制:131072 KB 分值: 640 定義F(n)表示最小公倍數為n的二元組的數量。 即:如果存在兩個數(二元組)X,Y(X <= Y),它們的最小公倍數為N,則F(n)的計數加1。 例如:F(6) = 5,因為[2,3] [1,6] [2,6] [3,6] [6,6]的最小公倍數等於6。 給出一個區間[a,b],求最小公倍數在這個區間的不同二元組的數量。 例如:a = 4,b = 6。符合條件的二元組包括: [1,4] [2,4] [4,4] [1,5] [5,5] [2,3] [1,6] [2,6] [3,6] [6,6],共10組不同的組合。
輸入數據包括2個數:a, b,中間用空格分隔(1 <= a <= b <= 10^11)。
Output
輸出最小公倍數在這個區間的不同二元組的數量。
Input示例
4 6
Output示例
10
數學問題 莫比烏斯反演
請開始你的反演!
設:
$$ans(n)=\sum_{i=1}^{n} \sum_{j=1}^{n} [\frac{i*j}{gcd(i,j)}<=n]$$
那麽 $ans(b)-ans(a-1)$ 就是最終答案
嘗試化簡上面的式子:
$$\sum_{i=1}^{n} \sum_{j=1}^{n} [\frac{i*j}{gcd(i,j)}<=n]$$
$$\sum_{d=1}^{n} \sum_{i=1}^{\frac{n}{d}} \sum_{j=1}^{\frac{n}{d}} [i*j<=\frac{n}{d}] [gcd(i,j)==1]$$
$$\sum_{d=1}^{n} \sum_{k=1}^{\frac{n}{d}} \mu(k) \sum_{i=1}^{\frac{n}{d}} \sum_{j=1}^{\frac{n}{d}} [i*k*j*k<=\frac{n}{d}] $$
$$\sum_{k=1}^{n} \mu(k) \sum_{d=1}^{\frac{n}{k}} \sum_{i=1}^{\frac{n}{dk}} \sum_{j=1}^{\frac{n}{dk}} [i*j*d<=\frac{n}{k^2}] $$
顯然d和k值大到一定程度,最後面就是0了,所以我們可以縮小求和上界:
$$\sum_{k=1}^{\sqrt n} \mu(k) \sum_{d=1}^{\frac{n}{k^2}} \sum_{i=1}^{\frac{n}{dk^2}} \sum_{j=1}^{\frac{n}{dk^2}} [i*j*d<=\frac{n}{k^2}] $$
這個範圍很友好,我們可以枚舉$\mu(k)$,求滿足條件的i j d三元組數量。
需要求的三元組是無序的,為了不重不漏地計數,我們可以分別求出有序(單調上升)的三元組數量,對於其中三個數各不同的、有兩個數相同的、三個數都相同的分別計數,然後乘以對應的組合數即可。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 #define LL long long 7 using namespace std; 8 const int mxn=1000010; 9 int pri[mxn],mu[mxn],cnt=0; 10 bool vis[mxn]; 11 void init(){ 12 mu[1]=1; 13 for(int i=2;i<mxn;i++){ 14 if(!vis[i]){ 15 pri[++cnt]=i; 16 mu[i]=-1; 17 } 18 for(int j=1;j<=cnt && pri[j]*i<mxn;j++){ 19 vis[pri[j]*i]=1; 20 if(i%pri[j]==0){mu[pri[j]*i]=0;break;} 21 mu[pri[j]*i]=-mu[i]; 22 } 23 } 24 return; 25 } 26 LL calc(LL n){ 27 if(!n)return 0; 28 LL i,j,k,ed=floor(sqrt(n)); 29 LL res=0,tmp=0; 30 for(k=1;k<=ed;k++){ 31 if(mu[k]){ 32 tmp=0; 33 LL ED=n/(k*k); 34 for(i=1;i*i*i<=ED;i++){ 35 for(j=i+1;j*j*i<=ED;j++) 36 tmp+=(ED/(i*j)-j)*6+3; 37 tmp+=(ED/(i*i)-i)*3; 38 tmp++; 39 } 40 res+=mu[k]*tmp; 41 } 42 } 43 return (res+n)/2; 44 } 45 LL a,b; 46 int main(){ 47 init(); 48 scanf("%lld%lld",&a,&b); 49 printf("%lld\n",calc(b)-calc(a-1)); 50 return 0; 51 }
51nod1222 最小公倍數計數