2019ICPC南京网络赛B super_log——扩展欧拉定理

题目

设函数

$$log_a*(x) = \begin{cases}
-1, & \text{ if } x < 1 \\
1+log_a*(log_ax) & \text{ if } x \geq 1
\end{cases}$$

求最小的正整数 $x$,使得 $log_a*(x) \geq b$

分析

通过将递归式展开,展开 $b$ 次等于1,所以 $x$ 为 $a^{a^{a^{...}}}$(共 $b$ 次)

由欧拉降幂公式

$$a^b= \begin{cases} a^{b \% \varphi(p)} &  gcd(a,p)=1 \\  a^b &  gcd(a,p)\neq 1,b < \varphi (p) \\  a^{b\% \varphi (p) + \varphi (p)} & gcd(a,p)\neq 1,b \geq \varphi (p) \end{cases}$$

用这个公式,需要讨论 $b$ 与 $\varphi(p)$ 的大小关系,很麻烦。

看网上的博客,有一种精妙的方法,只需重写 Mod 函数,就能当作 $a$ 与 $p$ 互素处理。证明见博客

要点:

  • 快速幂和cal函数都要换成Mod;
  • 最终答案需要模p
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
ll a, b, p;

ll Mod(ll x, ll mod)
{
    return x < mod ? x : x % mod + mod;
}

ll euler_phi(ll n)
{
    ll m = (ll)sqrt(n + 0.5);
    ll ans = n;
    for (ll i = 2; i <= m; i++)
    {
        if (n % i == 0)
        {
            ans = ans / i * (i - 1);
            while (n % i == 0)  n /= i;        //除尽
        }
    }
    if (n > 1)  ans = ans / n * (n - 1);    //剩下的不为1,也是素数
    return ans;
}

ll qpow(ll a, ll b, ll p)
{
    ll ret = 1;
    while(b)
    {
        if(b&1) ret = Mod(ret * a, p);
        a = Mod(a * a ,p);
        b >>= 1;
    }
    return ret;
}

ll cal(ll a, ll b, ll p)   //a^a^a..^a共b次
{
   // printf("%lld %lld\n", t, p);
    //if(t == 1)  return Mod(a, p);
    if(b == 0)  return Mod(1, p);
    if(p == 1)  return Mod(a, p);
    ll phip = euler_phi(p);
    return qpow(a, cal(a, b-1, phip), p);  //第一类和第三类
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%lld%lld%lld", &a, &b, &p);
        printf("%lld\n", cal(a, b, p) % p);  //这个取模不能少
    }
    return 0;
}

之前写了一种需要讨论 $b$  与 $\varphi(p)$ 大小的,

因为模数 $p \leq 1e6$,可以找找 $b$ 小于 $\varphi(p)$ 的情况

打表发现,

1 2 4 16 65536
1 3 27 97484987 739387
1 4 256 6084096 61392896
1 5 3125 8203125 8203125
1 6 46656 63878656 38438656
1 7 823543 70132343 33172343
1 8 16777216 21126656 19449856
1 9 87420489 27177289 45865289

当次数大于3时,只有 $a=2$ 可能小于 $\varphi(p)$,特判一下就好了。

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
ll a, b, p;
int table[10] = {1, 2, 4, 16,65536};

ll qpow(ll a, ll b, ll p)
{
    a = a%p;
    ll ret = 1%p;
    while(b)
    {
        if(b&1) ret = ret*a%p;
        a = a*a%p;
        b >>= 1;
    }
    return ret%p;
}

ll euler_phi(ll n)
{
    ll m = (ll)sqrt(n + 0.5);
    ll ans = n;
    for (ll i = 2; i <= m; i++)
    {
        if (n % i == 0)
        {
            ans = ans / i * (i - 1);
            while (n % i == 0)  n /= i;        //除尽
        }
    }
    if (n > 1)  ans = ans / n * (n - 1);    //剩下的不为1,也是素数
    return ans;
}

ll f(ll p, ll t)
{
    //printf("%lld %lld\n", p, t);
    if(t == 1)  return a%p;
    if(t == 2)  return qpow(a, a, p);
    if(t == 0)  return 1%p;
    if(p == 1)  return 0;
    ll phip = euler_phi(p);
    if(p % a == 0)  //t >= 3,若出现第二种情况,a只能为2
    {
        if(a == 2 && t <= 4 && table[t-1] < phip)
            //return qpow(a, f(p, t-1), p);
            return table[t]%p;
    }
    return qpow(a, f(phip, t-1)+phip, p);  //第一类和第三类
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%lld%lld%lld", &a, &b, &p);
        printf("%lld\n", f(p, b));
    }
    return 0;
}

参考链接:https://blog.csdn.net/qq_35914587/article/details/79883547

原文地址:https://www.cnblogs.com/lfri/p/11445393.html

时间: 2024-10-09 02:08:31

2019ICPC南京网络赛B super_log——扩展欧拉定理的相关文章

2019ICPC南京网络赛A题 The beautiful values of the palace(三维偏序)

2019ICPC南京网络赛A题 The beautiful values of the palace https://nanti.jisuanke.com/t/41298 Here is a square matrix of n * nn?n, each lattice has its value (nn must be odd), and the center value is n * nn?n. Its spiral decline along the center of the squar

[欧拉降幂][2019南京网络赛B]super_log

题意:输入a,b,p,求(底数a的右上角有b-1个a) 思路: 广义欧拉定理: AC代码: #include<bits/stdc++.h> typedef long long ll; using namespace std; ll a,b,m; ll vis[1000005]; ll prime[1000005],num=0; ll phi[1000005]; void getphi(ll n=1000000){ phi[1]=1; for(ll i=2;i<=n;i++){ if(!v

2019icpc南京网络赛 A 主席树

题意 给一个\(n\times n\)的螺旋矩阵,给出其中的\(m\)个点的值分别为各个点上数字的数位之和,给出\(q\)个询问,每次询问从\((x1,y1)\)到\((x2,y2)\)的子矩阵的和. 分析 用官方题解的方法\(O(1)\)推出点\((x,y)\)上的值,将这\(m\)个点按\(x\)排序后依次按\(y\)建主席树,查询时找到对应的\(x1\)和\(x2\)的历史版本,查询\(y1\)到\(y2\)的权值和就行了,\((query(y1,y2,1,n,rt[l],rt[r]))\

2018ICPC南京网络赛

2018ICPC南京网络赛 A. An Olympian Math Problem 题目描述:求\(\sum_{i=1}^{n} i\times i! \%n\) solution \[(n-1) \times (n-1)! \% n= (n-2)!(n^2-2n+1) \%n =(n-2)!\] \[(n-2+1)\times (n-2)! \% n= (n-3)!(n^2-3n+2) \%n =(n-3)! \times 2\] 以此类推,最终只剩下\(n-1\) 时间复杂度:\(O(1)\

计蒜客 2018南京网络赛 I Skr ( 回文树 )

题目链接 题意 : 给出一个由数字组成的字符串.然后要你找出其所有本质不同的回文子串.然后将这些回文子串转化为整数后相加.问你最后的结果是多少.答案模 1e9+7 分析 : 应该可以算是回文树挺裸的题目吧 可惜网络赛的时候不会啊.看着马拉车想半天.卒... 对于每一个节点.记录其转化为整数之后的值 然后在回文串插入字符的时候 不断维护这个信息就行了 其实很好理解.看一下代码就懂了 ( 如果你学过回文树的话... ) 就是多加了变量 val .维护语句 #include<bits/stdc++.h

super_log (广义欧拉降幂)(2019南京网络赛)

题目: In Complexity theory, some functions are nearly O(1)O(1), but it is greater then O(1)O(1). For example, the complexity of a typical disjoint set is O(nα(n))O(nα(n)). Here α(n)α(n) is Inverse Ackermann Function, which growth speed is very slow. So

ICPC2018南京网络赛 AC Challenge(一维状压dp)

AC Challenge 30.04% 1000ms 128536K Dlsj is competing in a contest with n (0 < n \le 20)n(0<n≤20) problems. And he knows the answer of all of these problems. However, he can submit ii-th problem if and only if he has submitted (and passed, of course)

南京网络赛题解 2018

J. Sum A square-free integer is an integer which is indivisible by any square number except 111. For example, 6=2⋅36 = 2 \cdot 36=2⋅3 is square-free, but 12=22⋅312 = 2^2 \cdot 312=22⋅3 is not, because 222^222 is a square number. Some integers could b

ACM 2018 南京网络赛H题Set解题报告

题目描述 给定\(n\)个数$a_i$,起初第\(i\)个数在第\(i\)个集合.有三种操作(共\(m\)次): 1 $u$ $v$ 将第$u$个数和第$v$个数所在集合合并 2 $u$ 将第$u$个数所在集合所有数加1 3 $u$ $k$ $x$ 问$u$所在集合有多少个数模$2^k$余$x$. 数据范围:\(n,m \le 500000,a_i \le 10^9, 0 \le k \le 30\). 简要题解 显然此题可以用set加启发式合并在\(O(n \log ^2 n)\)时间复杂度解