Powerful Number學習筆記

比較好的資源只是可能會轉很久
就是對於積性函數F(x)F(x)求前綴和。
構造出一個滿足對於任意質數p,F(p)=G(p)p,F(p) = G(p)的積性函數G(x)G(x)
那麼設H(x)=F(x)G(x)H(x) = \frac {F(x)}{G(x)},注意這裏是狄利克雷卷積意義下的除法。
F(x)=H(x)G(x)F(x) = H(x) G(x)
考慮F(p)=H(1)G(p)+H(p)G(1)=G(p)+H(p)F(p) = H(1)G(p) + H(p)G(1) = G(p) + H(p)(是積性函數所以G(1)=H(1)=1G(1) = H(1) = 1
所以H(p)=F(p)G(p)=0H(p) = F(p) - G(p) = 0
又因爲H(x)H(x)是兩個積性函數的商也是一個積性函數。
所以H(x)H(x)一定能表示成a2b3a^2b^3的形式(也叫powerful number\rm powerful \ number),如果我們需要不算重,那麼就讓bb不含平方因子即可。
積分一下1n3nb3db=O(n)\int_1^{\sqrt[3]n} \sqrt \frac n{b^3}{\rm d}b = O(\sqrt n)
所以npowerful number\leq n的\rm powerful\ number的數量是O(n)O(\sqrt n)的。
因爲F(x)=G(x)H(x)=H(x)G(x)\sum F(x) = \sum G(x)H(x) = \sum H(x) \sum G(x)
又因爲H(x)H(x)只有根號nn個地方有值,我們只需要快速求G(x)G(x)的前綴和即可。
至於快速求H(x)H(x)n\sqrt n個單點值,可以利用積性函數的性質快速求(猜結論,這個步驟和min25篩一樣H(pq)H(p^q)的值然後O(logn)O(\log n)求出H(x)H(x)的單點值。

Code\mathcal Code

#include<bits/stdc++.h>
#define LL long long
#define mod 1000000007
using namespace std;

LL n;
int K;
#define maxn 4000006
int pr[maxn],vis[maxn],cnt_pr,mu[maxn],mp[maxn];
int ar[maxn],usd[maxn],pw[maxn],pw2[maxn],inv[22],S[22][22];
LL Cube(LL a){ return a * a * a; }
LL sqr(LL a){ return a * a; }
int Pow(int b,int k){ int r=1;for(;k;k>>=1,b=1ll*b*b%mod) if(k&1) r=1ll*r*b%mod; return r; }
int calc(LL n){
	static int ans[maxn]={},usd[maxn]={};
	n %= mod;
	if(n < maxn && usd[n]) return ans[n];
	int r = 0;
	for(int i=1,s=n+1;i<=K;i++){
		s = 1ll * s * (n+1-i) % mod;
		r = (r + 1ll * S[K][i] * s % mod * inv[i+1]) % mod;
	}
	if(n < maxn) usd[n] = 1 , ans[n] = r;
	return r;
}

int main(){
	
	freopen("2.in","r",stdin);
	
	scanf("%lld%d",&n,&K);
	mu[1] = mp[1] = pw[1] = pw2[1] = inv[0] = inv[1] = 1;
	for(int i=2;1ll*i*i<=n;i++){
		if(!vis[i]) mu[i] = -1 , pr[cnt_pr++] = i , mp[i] = i;
		for(int j=0;sqr(pr[j]*i)<=n;j++){
			vis[pr[j] * i] = 1;
			mp[pr[j] * i] = pr[j];
			if(i % pr[j] == 0){
				mu[i * pr[j]] = 0;
				break;
			}
			mu[i * pr[j]] = -mu[i];
		}
		pw[i] = Pow(i,K) , pw2[i] = pw[i] * 1ll * pw[i] % mod;
	}
	for(int i=2;i<=K+1;i++)
		inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod;
	S[0][0] = 1;
	for(int i=1;i<=K;i++)
		for(int j=1;j<=i;j++)
			S[i][j] = (S[i-1][j-1] + 1ll * S[i-1][j] * j) % mod;
	int ans = 0;
	for(int i=1;Cube(i)<=n;i++)	if(mu[i]){
		for(int j=1,LIM=floor(sqrt(n/Cube(i)));j<=LIM;j++){
			ar[0] = 0;
			int sm = 1;
			for(int k=i;k>1;k/=mp[k])
				if(!usd[mp[k]])	
					ar[++ar[0]] = mp[k] , sm = 1ll * sm * (pw[mp[k]] - pw2[mp[k]]) % mod , usd[mp[k]] = 1;
			for(int k=j;k>1;k/=mp[k])
				if(!usd[mp[k]])
					ar[++ar[0]] = mp[k] , sm = 1ll * sm * (pw[mp[k]] - pw2[mp[k]]) % mod , usd[mp[k]] = 1;
			ans = (ans + 1ll * sm * calc(n / Cube(i) / sqr(j))) % mod;
			for(int k=1;k<=ar[0];k++)
				usd[ar[k]] = 0;
		}
	}
	printf("%d\n",(ans+mod)%mod);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章