1. 程式人生 > 實用技巧 >TopCoder - 12584 SRM 582 Div 1 SemiPerfectPower (莫比烏斯反演)

TopCoder - 12584 SRM 582 Div 1 SemiPerfectPower (莫比烏斯反演)

TopCoder - 12584 SRM 582 Div 1 SemiPerfectPower (莫比烏斯反演)

題目大意:

給定\(L,R\),求\([L,R]\)中能夠表示為\(a\cdot b^c(1\leq a<b,c>1)\)的數(SemiPerfect數)的個數

\(R\leq 8\cdot 10^{16}\)

解題思路

首先顯然可以通過作差轉化為求\([1,n]\)內的個數

接下來考慮簡化\(c\)的情形

推論:任何一個SemiPerfect數可以表示為\(c\leq 3\)的形式

證明:若\(c>3\),對於\(n=a\cdot b^c(c>3)\)

\(2|c\)

時,顯然存在形如\(n=a\cdot (b^{\frac{c}{2}})^{2}\)的表示

\(2\not |c\)時,可以表示為\(n=(a\cdot c)\cdot (b^{\frac{c-1}{2}})^2\)同樣合法

接下來考慮對於兩種情況分類討論

為了便於敘述,令\(F(n)=\max \lbrace k\in \N^+|\ k^2|n\rbrace\)

\(G(n)=[\nexists k>1,k^3|n]\)

Part1 \(c=2\)

為了避免重複,強制每一個數\(n\)的唯一表示為

\(n=a\cdot b^2(F(a)=1,a<b)\)

由於\(a<b\)

,所以顯然\(n>a^3\),即\(a<n^{\frac{1}{3}}\)

暴力列舉\(a\),預處理\(n^{\frac{1}{3}}\)中所有的\(G(i)\)即可

\[\ \]

Part \(c=3\)

同樣的,限制條件為\(n=a\cdot b^3,(G(a)=1,a<b)\),得到\(a<n^{\frac{1}{4}}\)

但是由於\(c=2,3\)兩部分有重複,還需額外考慮強制\(n\)不存在形如\(n=a'\cdot b'^2\)的表示

假設已知\(n=a\cdot b^3\),不存在\(n=a'\cdot b'^2\)的判定條件是

\(a'=\frac{n}{F^2(n)}\ge F(n)\)

,即\(F(n)\leq n^{\frac{1}{3}}\)

同時由於\(F(n)=F(a\cdot b)b\)

得到\(F(a,b)\leq a^{\frac{1}{3}}\)

由於等號右邊包含\(a\),考慮列舉\(a\),易求出\(L=F(a),d=\frac{a}{L^2}\),得到\(F(a\cdot b)\)的另一種表達形式

\(F(a\cdot b)=L \cdot \gcd (d,b)\cdot F(\frac{b}{\gcd(d,b)})\leq a^{\frac{1}{3}}\)

上面的轉化意為:\(L\)\(a\)中已經成對的部分自然取出,然後優先考慮為\(D\)匹配\(b\)中的因數成對,對於剩下的部分再重新計算答案

\[\ \]

化簡該式,得到\(L\cdot \gcd(d,b)F(\frac{b}{\gcd(d,b)})\leq a^{\frac{1}{3}}\)

式子包含$\gcd $,似乎具有莫比烏斯反演的性質

考慮計算\(b\in [a+1,(\frac{n}{a})^{\frac{1}{3}}]\)的數量

觀察到\(a^{\frac{1}{3}}\leq n^{\frac{1}{12}}\),上限只有\(25\)左右,可以考慮直接列舉\(F(\frac{b}{\gcd(b,d)})\)

令列舉的\(g=\gcd(b,d),F(\frac{b}{g})=f\),計算\(\gcd(\frac{b}{g},\frac{d}{g})=1,g\cdot f\cdot L\leq a^{\frac{1}{3}}\)\(b\)的數量

考慮直接從\(\frac{b}{g}\)中把\(f^2\)的因數提取出來,令\(\begin{aligned} L'=\lceil \frac{a+1}{gf^2}\rceil,R'=\lfloor \frac{(\frac{n}{a})^{\frac{1}{3}}}{gf^2}\rfloor \end{aligned}\),令\(i=\frac{b}{gf^2},x=\frac{d}{g}\),得到新的限制條件式子為

\(\gcd(x,f)=1,\gcd(i,x)=1,F(i)=1,i\in[L',R']\)

在確定了\(g,f\)之後,需要考慮的限制就是\(\gcd(i,x)=1,F(i)=1,i\in[L',R']\)

由於包含\(\gcd\),不妨用莫比烏斯反演計算該式,得到表示式為

\(Sum=\sum_{k|x}\mu(k)\sum_{i\in [L',R']} [k|i\ \text{and}\ F(i)=1]\)

對於\(k\),計算\(\sum_{i\in[L',R']}[k|i\ \text{and}\ F(i)=1]\)可以歸納為計算

\(\sum_{i=\frac{n}{k}} [F(ik)=1]\),一共有\(n^{\frac{1}{3}}\ln n\)種不同的權值,可以暴力預處理得到

列舉\(d\)的因數對於所有的上面的式子計算,可能的\(g,f\)並不多,可以直接列舉

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pb push_back
#define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)

class SemiPerfectPower {
public:
	static const int N=450000,M=20000;
	int w[N],notpri[N],pri[N],pc,F[N],G[N];
	vector <int> S[N],Fac[N];
	ll gcd(ll a,ll b){ return b==0?a:gcd(b,a%b); }
	SemiPerfectPower(){
		// 預處理F,G ,w[i]=\mu(i) S[k][i]=\sum_{j \in [1,i]}  F(i,k)=1
		rep(i,1,sqrt(N)) rep(j,1,(N-1)/i/i) F[i*i*j]=i;
		rep(i,2,pow(N,1/3.0)) rep(j,1,(N-1)/i/i/i) G[i*i*i*j]=1;
		rep(i,1,M-1) for(int j=i;j<M;j+=i) Fac[j].pb(i);
		w[1]=1;
		rep(i,2,N-1) {
			if(!notpri[i]) pri[++pc]=i,w[i]=-1;
			for(int j=1;i*pri[j]<N && j<=pc;++j) {
				notpri[i*pri[j]]=1;
				if(i%pri[j]==0) {
					w[i*pri[j]]=0;
					break;
				} 
				w[i*pri[j]]=-w[i];
			}
		}
		rep(i,1,N-1) if(w[i]) {
			S[i].resize(N/i+1);
			rep(j,1,(N-1)/i) S[i][j]=S[i][j-1]+(F[i*j]==1);
		}
	}

	ll Solve2(ll n){
		ll ans=0,UX=pow(n,1/3.0);
        // 防止浮點誤差
		if((UX+1)*(UX+1)*(UX+1)<=n) UX++;
		if(UX*UX*UX>n) UX--;
		rep(i,1,UX) if(F[i]==1) {
			ll UY=sqrt(n/i);
            // 防止浮點誤差
			if(i*(UY+1)*(UY+1)<=n) UY++;
			if(i*UY*UY>n) UY--;
			ans+=max(0ll,UY-i);
		}
		return ans;
	}

	ll Solve3(ll n){
		ll UX=pow(n,0.25); 
		// 列舉c的上界
		ll ans=0;
		if((UX+1)*(UX+1)*(UX+1)*(UX+1)<=n) UX++;
		rep(x,1,UX) if(!G[x]) {
			ll UY=pow(n/x,1.0/3.0),U=pow(x,1/3.0);
			
			// 防止浮點誤差
			if((U+1)*(U+1)*(U+1)<=x) U++;
			if(U*U*U>x) U--;
			if(x*(UY+1)*(UY+1)*(UY+1)<=n) UY++;
			if(x*UY*UY*UY>n) UY--;

			int L=F[x],D=x/L/L;
			for(int G:Fac[D]) {
				for(int g:Fac[G]) {
					if(g*L>U) break;
					rep(f,1,U/g/L) if(gcd(f,D/g)==1) {
						int L=x/G/f/f,R=UY/G/f/f;
						ans+=w[G/g]*(S[G/g][R]-S[G/g][L]);
					}
				}
			}
		}
		return ans;
	}
	ll Solve(ll n) {
		return Solve2(n)+Solve3(n);
	}
	ll count(ll L,ll R) {
		return Solve(R)-Solve(L-1);
	}
};