2019 南京ICPC网络赛 B super_log(幂塔函数求模、扩展欧拉降幂)

本文探讨了迭代对数函数log*及其在计算复杂性理论中的应用,特别是如何找到最小正整数x,使得log*a(x)达到特定阈值b。文章详细解析了如何使用欧拉降幂法解决此问题,包括费马小定理、扩展欧拉降幂法的证明及其实现算法。

注:笔者是一名十八线蒟蒻 ACMerACMerACMer,因此文中可能有许多 BUGBUGBUG ,请大佬们在评论区下留言,我会尽快改进。

原题

时间限制:1000ms1000ms1000ms,空间限制:131072K131072K131072K
In Complexity theory, some functions are nearly O(1)O(1)O(1), but it is greater then O(1)O(1)O(1). For example, the complexity of a typical disjoint set is O(nα(n))O(nα(n))O(nα(n)). Here α(n)α(n)α(n) is Inverse Ackermann Function, which growth speed is very slow. So in practical application, we often assume α(n)≤4α(n)≤4α(n)4.

However O(α(n))O(α(n))O(α(n)) is greater than O(1)O(1)O(1), that means if nnn is large enough, α(n)α(n)α(n) can greater than any constant value.

Now your task is let another slowly function log∗xlog^{*}xlogx reach a constant value bbb. Here log∗xlog^{*}xlogx is iterated logarithm function, it means “the number of times the logarithm function iteratively applied on xxx before the result is less than logarithm base aaa”.
Formally, consider a iterated logarithm function log∗xlog^{*}xlogx
在这里插入图片描述
Find the minimum positive integer argument xxx, let loga∗x≥blog^{*}_{a}x\geq blogaxb The answer may be very large, so just print the result xxx after mod mmm.

Input
The first line of the input is a single integer T(T≤300)T(T≤300)T(T300) indicating the number of test cases.

Each of the following lines contains 333 integers aaa , bbb and mmm.

1≤a≤1e61≤a≤1e61a1e6
0≤b≤1e60≤b≤1e60b1e6
1≤m≤1e61≤m≤1e61m1e6
Note that if a=1a=1a=1, we consider the minimum number xxx is 111.
Output
For each test case, output xxx mod mmm in a single line.
Hint
In the 4−th4−th4th query, a=3a=3a=3 and b=2b=2b=2. Then log3∗(27)=1+log3∗(3)=2+log3∗(1)=3+(−1)=2≥blog_{3}^* (27) = 1+ log_{3}^* (3) = 2 + log_{3}^* (1)=3+(-1)=2\geq blog3(27)=1+log3(3)=2+log3(1)=3+(1)=2b, so the output is 272727 mod 161616 = 111111.
样例输入

5
2 0 3
3 1 2
3 1 100
3 2 16
5 3 233

样例输出

1
1
3
11
223

题面分析

总结起来就是:给出a,b,ma,b,ma,b,mloga∗xlog^{*}_{a}xlogax的计算方法,求最小的正整数xxx,使得 loga∗x≥blog^{*}_{a}x\geq blogaxb 输出 x mod m。x \ mod \ m。x mod m **
一般对于数学题,我们可以先试几个数来找找规律。
我们以a=2a=2a=2为例,建议以下过程读者可以自己手推或者利用代码暴力打表。
b=0b=0b=0时,x=1x=1x=1
b=1b=1b=1时,倒推回去可以得到x=2x=2x=2
同理,b=2b=2b=2时,得到x=4x=4x=4
b=3b=3b=3时,x=16x=16x=16
b=4b=4b=4时,x=65536x=65536x=65536
写到这里我们似乎看到了规律:222212^{1}21444222^{2}22,161616242^{4}24,6553665536655362162^{16}216,所以我们总结以下得到
答案是2共b个2222...22^{2^{2^{2^{...^{2}}}}}_{_{_{共b个2}}}2b2222...2
那为了确认这个结论是否正确,我们再以a=3a=3a=3为例,请读者试着自行推导。
当然我们同样可以得到答案是3共b个3333...33^{3^{3^{3^{...^{3}}}}}_{_{共b个3}}3b3333...3
所以,我们可以假设:对于a,b,ma,b,ma,b,m,答案为a共b个aaaa...amoda^{a^{a^{a^{...^{a}}}}}_{_{_{共b个a}}} modabaaaa...amod mmm
数学题就是大胆猜想从不求证。但为了显得这篇博客很正经还是证明一下
证明:我们将a共b个aaaa...aa^{a^{a^{a^{...^{a}}}}}_{_{_{共b个a}}}abaaaa...a记为 f(a,b)f(a,b)f(a,b),则
loga∗(f(a,b))log^{*}_{a}(f(a,b))loga(f(a,b))
=1+loga∗(f(a,b−1))=1+log^{*}_{a}(f(a,b-1))=1+loga(f(a,b1))
=2+loga∗(f(a,b−2))=2+log^{*}_{a}(f(a,b-2))=2+loga(f(a,b2))
.........
=b−1+loga∗(f(a,1))=b-1+log^{*}_{a}(f(a,1))=b1+loga(f(a,1))
=b+loga∗(a)=b+log^{*}_{a}(a)=b+loga(a)
=b+1+loga∗(1)=b+1+log^{*}_{a}(1)=b+1+loga(1)
=b+1−1=b+1-1=b+11
=b=b=b
于是该问题就转化为求这个幂塔函数a共b个aaaa...amoda^{a^{a^{a^{...^{a}}}}}_{_{_{共b个a}}} modabaaaa...amod mmm的结果。
因为1≤a≤1e61≤a≤1e61a1e60≤b≤1e60≤b≤1e60b1e61≤m≤1e61≤m≤1e61m1e6,暴力算法直接超出范围,队友赛后用pythonpythonpython纯暴力算到超时,因此考虑新的策略。
我们可以先处理简单的情况:ab mod m,ba^b\ mod\ m,bab mod m,b是个很大的数字,如果可以处理的话就可以递归解决问题。
这里就要请出本题的主角:欧拉降幂

欧拉降幂

首先,我们有费马小定理ap−1≡1a^{p-1}\equiv 1ap11(mod p),(gcd(a,p)=1)(mod\ p),(gcd(a,p)=1)(mod p),(gcd(a,p)=1)
又因为φ(p)=p−1(p∈prime)φ(p)=p-1(p∈prime)φ(p)=p1(pprime),因此我们有aφ(p)≡1(mod p),(gcd(a,p)=1)a^{φ(p)}\equiv 1(mod \ p),(gcd(a,p)=1)aφ(p)1(mod p),(gcd(a,p)=1)
所以ab≡ab modφ(p)(modp)a^b\equiv a^{b\ modφ(p)}(mod p)abab modφ(p)(modp),我们称之为 欧拉降幂
但在本题中,gcd(a,p)gcd(a,p)gcd(a,p)不一定为111,因此我们引入扩展欧拉降幂

扩展欧拉降幂

首先我们给出结论
在这里插入图片描述
以下是证明,可以选择性跳过毕竟会用就行
b<φ(p)b<φ(p)b<φ(p)时易知。
b≥φ(p)b\geq φ(p)bφ(p)时证明如下:
( 以下证明内容来自 scau_bi 的CN博客 https://www.cnblogs.com/bibibi/p/10269051.html)
首先我们证明一个引理。
引理:对于mmm的一个质数因子ppp,有
pc=pc modφ(m)+φ(m)(mod m)p^c=p^{c\ mod φ(m)+φ(m)}(mod\ m)pc=pc modφ(m)+φ(m)(mod m)
证:
我们设m=s∗pr,gcd(s,p)=1m=s*p^{r},gcd(s,p)=1m=spr,gcd(s,p)=1
pφ(s)≡1(modp^{φ(s)}\equiv1(modpφ(s)1(mod s),gcd(s,p)=1s),gcd(s,p)=1s),gcd(s,p)=1(费马小定理)
因为φ(m)=φ(s)∗φ(pr)φ(m)=φ(s)*φ(p^{r})φ(m)=φ(s)φ(pr)φφφ是积性函数,即φ(i)φ(j)=φ(i∗j)φ(i)φ(j)=φ(i*j)φ(i)φ(j)=φ(ij)
pφ(m)=pφ(s)φ(pr)≡1φ(pr)≡1(mod s)p^{φ(m)}=p^{φ(s)^{φ(p^{r})}}\equiv 1^{φ(p^{r})}\equiv1(mod\ s)pφ(m)=pφ(s)φ(pr)1φ(pr)1(mod s)
我们设pφ(m)=k∗s+1p^{φ(m)}=k*s+1pφ(m)=ks+1
两边同乘prp^rpr,得
pφ(m)+r=k∗s∗pr+pr=k∗m+prp^{φ(m)+r}=k*s*p^r+p^r=k*m+p^rpφ(m)+r=kspr+pr=km+pr
所以 pφ(m)+r≡pr(mod m)p^{φ(m)+r}\equiv p^r(mod\ m)pφ(m)+rpr(mod m)
于是我们可以把这个式子推广,得到
pk∗φ(m)+r≡pr(mod m)(k≥0)p^{k*φ(m)+r}\equiv p^r(mod\ m)(k\geq 0)pkφ(m)+rpr(mod m)(k0)--------------------(①)
又因为φ(m)φ(m)φ(m)
=φ(s)∗φ(pr)=φ(s)*φ(p^r)=φ(s)φ(pr)
≥φ(pr)\geqφ(p^r)φ(pr)
=(p−1)∗pr−1=(p-1)*p^{r-1}=(p1)pr1(因为对于prp^rpr,除了ppp的倍数以外都与其互质,因此φ(pr)=pr−pr−1=(p−1)∗pr−1φ(p^r)=p^r-p^{r-1}=(p-1)*p^{r-1}φ(pr)=prpr1=(p1)pr1)
≥r\geq rr
(这一步的证明:
p=2p=2p=2时可以用导数易得其成立。
p>2p>2p>2(p−1)∗pr−1≥(p−1)∗er−1≥(p−1)∗(r−1+1)=(p−1)∗r≥r(p-1)*p^{r-1}\geq (p-1)*e^{r-1}\geq(p-1)*(r-1+1)=(p-1)*r\geq r(p1)pr1(p1)er1(p1)(r1+1)=(p1)rr
这里利用了ex≥x+1这个性质e^x\geq x+1这个性质exx+1,因为x+1x+1x+1ex在(0,1)的切线方程e^x在(0,1)的切线方程ex(0,1)线
因此pc(c≥r)p^c(c \geq r)pc(cr)
≡pc−r+r(mod m)\equiv p^{c-r+r}(mod\ m)pcr+r(mod m)
≡pc−r∗pr(mod m)\equiv p^{c-r}*p^r(mod\ m)pcrpr(mod m)
≡pc−r∗pr+φ(m)(mod m)\equiv p^{c-r}*p^{r+φ(m)}(mod\ m)pcrpr+φ(m)(mod m)
≡pc+φ(m)(mod m)(c≥r)\equiv p^{c+φ(m)}(mod\ m)(c \geq r)pc+φ(m)(mod m)(cr)
因为c≥r,r≥φ(m)c\geq r,r\geq φ(m)cr,rφ(m),故c≥φ(m)c\geqφ(m)cφ(m)
那我们利用①式得到
pc+φ(m)≡pc modφ(m)+φ(m)(mod m),c≥φ(m)p^{c+φ(m)}\equiv p^{c\ modφ(m)+φ(m)}(mod\ m),c\geq φ(m)pc+φ(m)pc modφ(m)+φ(m)(mod m),cφ(m)--------------------(②)
而对于pkcp^{k^c}pkc,我们也可以通过②式有
pkc≡pkc≡pφ(m)+kc≡(pk)c+φ(m)≡(pk)c modφ(m)+φ(m)(mod m)p^{k^c}\equiv p^{kc}\equiv p^{φ(m)+kc}\equiv (p^k)^{c+φ(m)}\equiv (p^k)^{c\ modφ(m)+φ(m)}(mod\ m)pkcpkcpφ(m)+kc(pk)c+φ(m)(pk)c modφ(m)+φ(m)(mod m)
因此,我们把一个任意数aaa拆成p1a1p2a2...pkakp_{1}^{a_{1}}p_{2}^{a_{2}}...p_{k}^{a_{k}}p1a1p2a2...pkak,则相乘后可以得到
ac≡ac modφ(m)+φ(m)(mod m),(c≥φ(m))a^c\equiv a^{c\ modφ(m)+φ(m)}(mod\ m),(c\geqφ(m))acac modφ(m)+φ(m)(mod m),(cφ(m))
终于证毕。建议想学懂原理的读者自行手推一遍!
好,有了解决的办法,我们就考虑递归写一个函数f(b,p)f(b,p)f(b,p)bbb为递归的层数,ppp是当前的模数。
每一次都利用快速幂实现af(b−1,φ(p))(mod p)a^{f(b-1,φ(p))}(mod\ p)af(b1,φ(p))(mod p)的调用。到最后一层返回aaa或者a mod φ(p)+φ(p)a\ mod\ φ(p)+φ(p)a mod φ(p)+φ(p)
注意在回溯时快速幂的结果也要根据扩展欧拉降幂进行改变!

AC代码(4ms)

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
long long a,b,m;
long long phi(long long n)
{
    long long ans = n;
    for(int i = 2; i*i <= n; i++)
    {
        if(n % i == 0)
        {
            ans -= ans/i; //等价于通项,把n乘进去
            while(n % i == 0) //确保下一个i是n的素因数
                n /= i;
        }
    }
    if(n > 1)ans -= ans/n; //最后可能还剩下一个素因数没有除
    return ans;
}
long long MOD(long long a,long long mm)//扩展欧几里得的结果
{
	return a>=mm?a%(mm)+(mm):a;
}
long long qsm(long long a,long long b,long long c)//快速幂
{
	if(!c)
		return 0;
    long long ans=1,base=a;
    while(b!=0)
	{
        if(b&1)
        ans=MOD(ans*base,c);
        base=MOD(base*base,c);//注意这两行!回溯时也要根据扩展欧拉降幂!
        b>>=1;
	}
	return MOD(ans,c);//答案也要!
}
long long f(long long b,long long mm)
{
	if(mm==1)
		return MOD(a,1);//模数为1时停止计算,因为之后的结果都是相同的
	if(b==1)
	{
		return MOD(a,mm);//最后一层的情况
	}
	return qsm(a,f(b-1,phi(mm)),mm);//递归调用
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%lld%lld%lld",&a,&b,&m);
		if(b==0 || a==1 || m==1)//特殊情况直接输出
		{
			printf("%lld\n",1%m);
			continue;
		}
		if(b==1)//特殊情况直接输出
		{
			printf("%lld\n",a%m);
			continue;
		}
		long long ans=f(b,m)%m;
		printf("%lld\n",ans);
	}
}

后记

昨天比赛时没能想到快速幂回溯,然后就是无尽的WA…,主要还是菜。
除了从外到内的递归法外,这题其实还可以从内到外来做,不容易错,有兴趣的读者可以尝试。
当然,这题也可以推广到更一般的问题:求x1x2...xnmod mx_1^{x_2^{...^{x_n}}}mod\ mx1x2...xnmod m,只要将上面的代码微调即可。
最后的最后,感谢一波赛后蔡队一针见血的指点。CSLNB!
DrGilbert 2019.9.2

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值