SPOJ22549 DIVFACT4 - Divisors of factorial (extreme) 題解
阿新 • • 發佈:2020-08-29
SP22549 DIVFACT4 - Divisors of factorial (extreme)
對於每組詢問\(,\)小於\(\sqrt n\)的部分暴力\(,\)大於\(\sqrt n\)的部分可以數論分塊\(.\)
問題變為若干個詢問區間質數個數的問題\(,\)且詢問端點\((\) 除了其中最多一個 \()\) 都是形如\(\lfloor \frac{n}{i} \rfloor\) 的數\(,\)因此\(Min25\)篩即可解決\(.\)
\(O(T(\large \sqrt{n}+\frac{n^{\frac{3}{4}}}{\log n}))\)
注意模數很大\(,\)要使用快速乘\(.\)
程式碼\(:\)
#include <bits/stdc++.h> #define LL long long #define db long double using namespace std; const int M = 1000050; int p[78498+50],cntp,pre[M]; inline void sieve(int n){ static bool vis[M]; static int i,j; memset(vis,0,sizeof(vis)); for (i = 2; i <= n; ++i){ pre[i] = pre[i-1]; if (!vis[i]) p[++cntp] = i,++pre[i]; for (j = 1; i * p[j] <= n; ++j){ vis[i*p[j]] = 1; if (i % p[j] == 0) break; } } } LL P; inline LL mul(LL x,LL y){ static LL ans; x %= P,y %= P,ans = x*y-P*(LL)((db)(x)*y/P); if (ans < 0) ans += P; else if (ans >= P) ans -= P; return ans; } inline LL power(LL x,LL y){ static LL r; r = 1; while (y){ if (y&1) r = mul(r,x); x = mul(x,x),y>>=1; } return r; } inline LL calc(LL n,int p){ static LL r; r = 0; while (n >= p) n /= p,r += n; return r; } int id1[M],id2[M],cntid; LL n,m,num[M<<1],f[M<<1]; inline int Id(LL x){ return x <= m ? id1[x] : id2[n/x]; } inline void Min25(){ LL l = 1,v; cntid = 0; m = min(n,(LL)(sqrt(n)) + 1); if (n <= 1000000) return; while (l <= n){ v = n/l; if (v <= m) id1[v] = ++cntid; else id2[n/v] = ++cntid; num[cntid] = v,f[cntid] = v-1,l = n/v+1; } register int i,j; for (i = 1; i <= cntp && (LL)p[i] * p[i] <= n; ++i) for (v = (LL)p[i] * p[i],j = 1; j <= cntid && num[j] >= v; ++j) f[j] -= f[Id(num[j]/p[i])]-(i-1); } inline LL ask(LL x){ return (x <= 1000000) ? pre[x] : f[Id(x)]; } inline void solve(){ int i; LL ans = 1%P,l = 1,r,v,lst = 0,now; Min25(); for (i = 1; i <= cntp && (LL)p[i] * p[i] <= n; ++i) ans = mul(ans,1+calc(n,p[i])),++lst,l = p[i]+1; while (l <= n) v = n/l,r = n/v,now = ask(r),ans = mul(ans,power(v+1,now-lst)),l = r+1,lst = now; cout << ans << '\n'; } int main(){ sieve(1000000); int T; cin >> T; while (T--) cin >> n >> P,solve(); return 0; }