2022 年 1 月 13 日
阿新 • • 發佈:2022-01-13
CF27E Number With The Given Amount Of Divisors
即把 \(n\) 分解成 \((k_1+1)(k_2+1)\dots(k_n+1)\) 的形式,配給一些質數作為指數,使得 \(\prod p_i^{k_i}\) 最小。暴力搜尋即可。
有一個小性質:可以發現 \(2\) 一定是最小答案的質因數,且其質因數的指數隨底數的增大而不增。
#include<cstdio> #include<algorithm> #include<stack> int vis[60001], prime[60001], tot, pps[1001]; long long pp[1001][1001]; long long ans = 0x7fffffffffffffffll; void solve(int i, int n, long long cur) { if (cur > ans) return; if (i > 1000) return; if (n == 1) return void(ans = cur); std::stack<int> lst; for (int j = 1; j * j <= n; j++) { if (n % j == 0) { if (j * j != n && j != 1) lst.push(j); int k = n / j - 1; if (k > pps[i]) continue; if (1e18 / cur <= pp[i][k]) continue; solve(i + 1, j, cur * pp[i][k]); } } while (!lst.empty()) { int k = lst.top() - 1, j = lst.top(); lst.pop(); if (k > pps[i]) continue; if (1e18 / cur <= pp[i][k]) continue; solve(i + 1, n / j, cur * pp[i][k]); } } int main() { for (int i = 2; i <= 60000; i++) { if (!vis[i]) prime[++tot] = i; for (int j = 1; j <= tot; j++) { int x = prime[j]; if (i * x > 60000) break; vis[i * x] = 1; if (i % x == 0) break; } } for (int i = 1; i <= 1000; i++) { pp[i][0] = 1, pp[i][1] = prime[i], pps[i] = 1; while (1e18 / pp[i][pps[i]] >= prime[i]) pps[i]++, pp[i][pps[i]] = pp[i][pps[i] - 1] * prime[i]; } int n; scanf("%d", &n), solve(1, n, 1); printf("%lld\n", ans); }
洛谷 P2054 [AHOI2005]洗牌
設 \(f(x)\) 為處於位置 \(x\) 的數在一次洗牌後的位置。有:
\[f(x)=\begin{cases} 2x&x\leq\frac n2\\ 2\left(x-\frac n2-1\right)+1&x\gt\frac n2 \end{cases} \]即
\[f(x)=\begin{cases} 2x&x\leq\frac n2\\ 2x-n-1&x\gt\frac n2 \end{cases} \]在模 \(n+1\) 意義下可以表示為 \(f(x)\equiv 2x\)。那麼經過 \(m\) 次洗牌後數字 \(x\)
則問題轉化成了求方程 \(2^mx\equiv L\pmod{n+1}\) 的最小正整數解。
#include<cstdio> typedef long long ll; ll n, m, L; ll mul(ll x, ll y) { __int128 t = ((__int128)x) * y; return (ll)(t % (n + 1)); } ll pow(ll x, ll y) { ll ret = 1; while (y) { if (y & 1) ret = mul(ret, x); x = mul(x, x), y >>= 1; } return ret; } ll exgcd(ll a, ll b, ll& x, ll& y) { if (!b) return x = 1, y = 0, a; ll d = exgcd(b, a % b, y, x); return y -= (a / b) * x, d; } ll inv(ll a) { ll ret = 0, x = 0; exgcd(a, n + 1, ret, x); return (ret % (n + 1) + (n + 1)) % (n + 1); } int main() { scanf("%lld%lld%lld", &n, &m, &L); printf("%lld\n", mul(L, inv(pow(2ll, m)))); }