[HDU-6834] Yukikaze and Smooth numbers
阿新 • • 發佈:2020-08-08
[HDU-6834] Yukikaze and Smooth numbers
題意:計算\([1,n]\)中只包含\([1,k]\)的質因數的數個數
讓人聯想到Min25篩的\(dp\)模型
設\(m=\sqrt n\),可以對於\(k > m\)和\(k\leq m\)討論
Case1:\(k\leq m\)
此時可以直接套用類似Min25篩的\(dp\)模型求解
令\(dp_{i,j}\)為\([1,j]\)只包含\([1,i]\)的質因數的數個數
則\(dp_{i,j}=\sum_k dp_{i-1,\lfloor \frac{j}{prime_i^k}\rfloor }\)
要求的是\(dp_{k,n}\)
直接寫當然是近似於\(O(m\cdot \pi(n))=O(\frac{n}{\log n})\)級別的
加上Min25篩的優化,令\(dp_i,j\)不包含單質數和1的情況,以減少轉移情況
如果從大到小考慮每個質數,那麼只需要考慮\(j\ge prime_i^2\)的第二維狀態,以減少很多的\(dp\)時間
沿用Min25篩複雜度證明,是\(O(\frac{n^{\frac{3}{4}}}{\log n})\)的
#define id(x) (x<=m?x:cnt-n/x+1) int dp[N],g[N],st[N],cnt; if(k==1){ puts("1"); continue; } m=sqrt(n),cnt=0; rep(i,1,n) st[++cnt]=i=n/(n/i),dp[cnt]=0; // 不包括質數本身和1 int sz=1; while(pri[sz+1]<=k) sz++; int p=0; rep(i,1,cnt){ while(p<sz && pri[p+1]<=st[i]) p++; g[i]=p; } rep(i,1,cnt) for(ll x=pri[sz]*pri[sz];x<=st[i];x*=pri[sz]) dp[i]++; for(reg int i=sz-1;i;--i) { for(reg int j=cnt,tmp=pri[i]*pri[i];st[j]>=tmp;--j) { reg int x=st[j]; while(x>=tmp) { x/=pri[i]; dp[j]+=dp[id(x)]+g[id(x)]-i+1; } } } printf("%d\n",dp[cnt]+sz+1);
\[\ \]
Case2 : \(k> m\)
可以把問題轉化為求不合法部分,即$\sum_{prime_i>k}\lfloor \frac{n}{prime_i}\rfloor $
採用數論分段計算$\lfloor \frac{n}{i}\rfloor $,那麼剩下的問題就是要求一段區間內的質數個數
同樣採用類似上面的模型,
令\(dp_{i,j}\)為\([1,j]\)內與前\([1,i]\)內質數互質的個數以及這些質數本身,不包括1
int n,m; int dp[N],g[N],st[N],cnt; #define id(x) (x<=m?x:cnt-n/x+1) int Count(int n) { if(n<N) return pcount[n]; ::n=n,m=sqrt(n),cnt=0; rep(i,1,n) st[++cnt]=i=n/(n/i),dp[cnt]=i-1; for(reg int i=1;pri[i]<=m;++i) { for(reg int j=cnt,tmp=pri[i]*pri[i];st[j]>=tmp;--j) { reg int k=st[j]/pri[i]; dp[j]-=dp[id(k)]-(i-1); } } return dp[cnt]; }
具體複雜度沒有算過,應該不會太高