B. super_log(2019ICPC区域网络赛南京站)
題目鏈接:https://nanti.jisuanke.com/t/41299
題目大意
已知函數(shù)loga?log_a^*loga??形式如下:
loga?(x)={?1,?if?x<11+loga?(logax),?if?x≥1log_a^*(x)= \begin{cases} -1 & \text{, if x<1} \\ 1+log_a^*(log_ax) & \text{, if x} \geq1 \end{cases} loga??(x)={?11+loga??(loga?x)?,?if?x<1,?if?x≥1?
現(xiàn)在給出a,b,ma,b,ma,b,m,要找到最小的正整數(shù)xxx,使得loga?(x)≥blog_a^*(x) \geq bloga??(x)≥b。由于xxx可能很大,所以需要取模mmm。
題目分析
多造幾組a,ba,ba,b去算xxx,可以發(fā)現(xiàn)這個(gè)問題就是求:
aaa...?btimesmodm\underbrace{a^{a^{a^{...}}}}_{b \text{ times}} mod \, m b?timesaaa...??modm
因?yàn)楸┝η筮@個(gè)數(shù)的過程量會(huì)非常大,所以需要對(duì)過程量取模。但是過程量是指數(shù),我們不能直接對(duì)其取模,這里就需要用上歐拉降冪。
ab≡{ab%φ(p)(modp),?gcd(a,?p)=1ab(modp),?b?<φ(p)ab%φ(p)+φ(p)(modp),?b≥φ(p)a^b \equiv \begin{cases} a^{b\% \varphi(p)} \, (mod \, p) & \text{, \,gcd(a, p)=1} \\ a^b \quad (mod \, p) & \text{, \, b <} \varphi(p) \\ a^{b\% \varphi(p) + \varphi(p)} \, (mod \, p) & \text{, \, b} \geq \varphi(p) \\ \end{cases} ab≡??????ab%φ(p)(modp)ab(modp)ab%φ(p)+φ(p)(modp)?,?gcd(a,?p)=1,?b?<φ(p),?b≥φ(p)?
知道了這些就里答案很接近了,我們可以每次都把問題遞歸分解為求利用歐拉降冪解指數(shù)部分的值,回歸時(shí)再計(jì)算層指數(shù)運(yùn)算的結(jié)果。
要注意:除了分解了bbb次可以返回之外,歐拉函數(shù)迭代到1也可以提前返回,可以減少大量不必要的運(yùn)算。
黑歷史記錄:
- 沒有想到模數(shù)的歐拉函數(shù)迭代到1可以提前返回的情況,因?yàn)槿魏握麛?shù)取模1都等于0,所以沒必要再繼續(xù)運(yùn)算。
- 沒有考慮到歐拉函數(shù)迭代到1是返回值為0時(shí)的處理1。
代碼如下
#include <iostream> #include <cstdio>using namespace std; typedef long long ll; const int maxn = 1e6 + 10; int T, a, b ,m; int phi[maxn]; ll prime[maxn]; bool vis[maxn]; //快速冪 ll quick_pow(ll x, ll n, ll Mod) {ll res = 1;while (n) {if (n & 1) res = (res * x) % Mod;x = (x * x) % Mod;n >>= 1;}return res; } //線性篩篩求歐拉函數(shù) void getphi(int n) {int i, j, tot = 0;phi[1] = 1;for (int i = 2; i <= n; i++) {if (!vis[i]) {prime[++tot] = i;phi[i] = i - 1;}for (int j = 1; j <= tot && i * prime[j] <= n; j++) {vis[i * prime[j]] = 1;if (i % prime[j] == 0) {phi[i * prime[j]] = phi[i] * prime[j];break;} else {phi[i * prime[j]] = phi[i] * (prime[j] - 1);}}} }int dfs(int a, int b, int m) {//歐拉函數(shù)迭代到1if (m == 1) return 0;//已經(jīng)迭代到最后一次了if (b == 0) return 1;int x = dfs(a, b - 1, phi[m]);//x為0是歐拉函數(shù)迭代到1返回的if (x < phi[m] && x) return quick_pow(a, x, m);else return quick_pow(a, x + phi[m], m); }int main() {getphi(maxn-10);scanf("%d", &T);while (T--) {scanf("%d %d %d", &a, &b, &m);printf("%d\n", dfs(a, b, m));}return 0; }參考鏈接
總結(jié)
以上是生活随笔為你收集整理的B. super_log(2019ICPC区域网络赛南京站)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ERROR 1366 (HY000):
- 下一篇: 使用Markdown写数学公式打出百分号