【省內訓練2018-11-25】Factorization
阿新 • • 發佈:2018-11-27
【思路要點】
- 用類似 篩 的過程進行搜尋即可。
- 具體來說,先用線性篩得出 以內的質數,記 表示第 個質數。
- 定義過程 表示處理大於等於 的質因子乘積不超過 ,小於 的質因子的指數資訊為 的數對答案的貢獻。
- 我們需要處理的即為 。
- 對於 ,我們將大於等於 的質因子乘積為質數的數單獨處理,顯然,這些數是屬於一類的,其個數即為 中質數的個數,可以事先篩出。
- 否則,列舉下一個質因數 ,滿足 ,並列舉其指數 ,滿足 ,呼叫 即可。
- 時間複雜度 ,其中 為統計答案帶來的複雜度因子。
【程式碼】
#include<bits/stdc++.h> using namespace std; const int MAXN = 3e5 + 5; typedef long long ll; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } ll n, val[MAXN], cnt[MAXN]; int limit, m, home1[MAXN], home2[MAXN]; map <vector <int>, ll> ans; int tot, prime[MAXN], f[MAXN]; void getans(ll x, int y, vector <int> now) { now.push_back(1); sort(now.begin(), now.end(), [&] (int x, int y) {return x > y; }); ll delta = -(y - 1); if (x <= limit) delta += cnt[home1[x]]; else delta += cnt[home2[n / x]]; if (delta > 0) ans[now] += delta; } void sieve() { for (ll i = 1, nxt; i <= n; i = nxt + 1) { ll tmp = n / i; val[++m] = tmp; cnt[m] = tmp - 1; if (tmp <= limit) home1[tmp] = m; else home2[n / tmp] = m; nxt = n / tmp; } for (int i = 1; i <= tot; i++) { for (int j = 1; 1ll * prime[i] * prime[i] <= val[j]; j++) { ll tmp = val[j] / prime[i]; int pos = 0; if (tmp <= limit) pos = home1[tmp]; else pos = home2[n / tmp]; cnt[j] -= cnt[pos] - (i - 1); } } } void work(ll x, int y, vector <int> now) { getans(x, y, now); if (x < prime[y] || y > tot) return; for (int i = y; i <= tot && 1ll * prime[i] * prime[i] <= x; i++) { ll val = prime[i], tmp = 1ll * prime[i] * prime[i]; for (int j = 1; tmp <= x; j++, val = tmp, tmp *= prime[i]) { vector <int> tnow = now; tnow.push_back(j + 1); sort(tnow.begin(), tnow.end(), [&] (int x, int y) {return x > y; }); ans[tnow]++; now.push_back(j); work(x / val, i + 1, now); now.pop_back(); } } } void init(int n) { for (int i = 2; i <= n; i++) { if (f[i] == 0) prime[++tot] = f[i] = i; for (int j = 1; j <= tot && prime[j] <= f[i]; j++) { int tmp = prime[j] * i; if (tmp > n) break; f[tmp] = prime[j]; } } } int main() { read(n); limit = sqrt(n) + 1; init(limit + 100); sieve(); vector <int> tmp; tmp.clear(); work(n, 1, tmp); printf(": 1\n"); for (auto x : ans) { static int cnt[36]; ll ans = x.second; memset(cnt, 0, sizeof(cnt)); for (auto y : x.first) { printf("%d ", y); ans *= ++cnt[y]; } printf(": %lld\n", ans); } return 0; }