注:笔者是一名十八线蒟蒻 A C M e r ACMer ACMer,因此文中可能有许多 B U G BUG BUG ,请大佬们在评论区下留言,我会尽快改进。
原题
时间限制:
1000
m
s
1000ms
1000ms,空间限制:
131072
K
131072K
131072K
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 n n n is large enough, α ( n ) α(n) α(n) can greater than any constant value.
Now your task is let another slowly function
l
o
g
∗
x
log^{*}x
log∗x reach a constant value
b
b
b. Here
l
o
g
∗
x
log^{*}x
log∗x is iterated logarithm function, it means “the number of times the logarithm function iteratively applied on
x
x
x before the result is less than logarithm base
a
a
a”.
Formally, consider a iterated logarithm function
l
o
g
∗
x
log^{*}x
log∗x
Find the minimum positive integer argument
x
x
x, let
l
o
g
a
∗
x
≥
b
log^{*}_{a}x\geq b
loga∗x≥b The answer may be very large, so just print the result
x
x
x after mod
m
m
m.
Input
The first line of the input is a single integer
T
(
T
≤
300
)
T(T≤300)
T(T≤300) indicating the number of test cases.
Each of the following lines contains 3 3 3 integers a a a , b b b and m m m.
1
≤
a
≤
1
e
6
1≤a≤1e6
1≤a≤1e6
0
≤
b
≤
1
e
6
0≤b≤1e6
0≤b≤1e6
1
≤
m
≤
1
e
6
1≤m≤1e6
1≤m≤1e6
Note that if
a
=
1
a=1
a=1, we consider the minimum number
x
x
x is
1
1
1.
Output
For each test case, output
x
x
x mod
m
m
m in a single line.
Hint
In the
4
−
t
h
4−th
4−th query,
a
=
3
a=3
a=3 and
b
=
2
b=2
b=2. Then
l
o
g
3
∗
(
27
)
=
1
+
l
o
g
3
∗
(
3
)
=
2
+
l
o
g
3
∗
(
1
)
=
3
+
(
−
1
)
=
2
≥
b
log_{3}^* (27) = 1+ log_{3}^* (3) = 2 + log_{3}^* (1)=3+(-1)=2\geq b
log3∗(27)=1+log3∗(3)=2+log3∗(1)=3+(−1)=2≥b, so the output is
27
27
27 mod
16
16
16 =
11
11
11.
样例输入
5
2 0 3
3 1 2
3 1 100
3 2 16
5 3 233
样例输出
1
1
3
11
223
题面分析
总结起来就是:给出
a
,
b
,
m
a,b,m
a,b,m与
l
o
g
a
∗
x
log^{*}_{a}x
loga∗x的计算方法,求最小的正整数
x
x
x,使得
l
o
g
a
∗
x
≥
b
log^{*}_{a}x\geq b
loga∗x≥b , 输出
x
m
o
d
m
。
x \ mod \ m。
x mod m。 **
一般对于数学题,我们可以先试几个数来找找规律。
我们以
a
=
2
a=2
a=2为例,建议以下过程读者可以自己手推或者利用代码暴力打表。
当
b
=
0
b=0
b=0时,
x
=
1
x=1
x=1。
当
b
=
1
b=1
b=1时,倒推回去可以得到
x
=
2
x=2
x=2。
同理,
b
=
2
b=2
b=2时,得到
x
=
4
x=4
x=4。
b
=
3
b=3
b=3时,
x
=
16
x=16
x=16。
b
=
4
b=4
b=4时,
x
=
65536
x=65536
x=65536。
写到这里我们似乎看到了规律:
2
2
2是
2
1
2^{1}
21,
4
4
4是
2
2
2^{2}
22,
16
16
16是
2
4
2^{4}
24,
65536
65536
65536是
2
16
2^{16}
216,所以我们总结以下得到
答案是
2
共
b
个
2
2
2
2
.
.
.
2
2^{2^{2^{2^{...^{2}}}}}_{_{_{共b个2}}}
2共b个2222...2。
那为了确认这个结论是否正确,我们再以
a
=
3
a=3
a=3为例,请读者试着自行推导。
当然我们同样可以得到答案是
3
共
b
个
3
3
3
3
.
.
.
3
3^{3^{3^{3^{...^{3}}}}}_{_{共b个3}}
3共b个3333...3。
所以,我们可以假设:对于
a
,
b
,
m
a,b,m
a,b,m,答案为
a
共
b
个
a
a
a
a
.
.
.
a
m
o
d
a^{a^{a^{a^{...^{a}}}}}_{_{_{共b个a}}} mod
a共b个aaaa...amod
m
m
m。
数学题就是大胆猜想从不求证。但为了显得这篇博客很正经还是证明一下
证明:我们将
a
共
b
个
a
a
a
a
.
.
.
a
a^{a^{a^{a^{...^{a}}}}}_{_{_{共b个a}}}
a共b个aaaa...a记为
f
(
a
,
b
)
f(a,b)
f(a,b),则
l
o
g
a
∗
(
f
(
a
,
b
)
)
log^{*}_{a}(f(a,b))
loga∗(f(a,b))
=
1
+
l
o
g
a
∗
(
f
(
a
,
b
−
1
)
)
=1+log^{*}_{a}(f(a,b-1))
=1+loga∗(f(a,b−1))
=
2
+
l
o
g
a
∗
(
f
(
a
,
b
−
2
)
)
=2+log^{*}_{a}(f(a,b-2))
=2+loga∗(f(a,b−2))
.
.
.
...
...
=
b
−
1
+
l
o
g
a
∗
(
f
(
a
,
1
)
)
=b-1+log^{*}_{a}(f(a,1))
=b−1+loga∗(f(a,1))
=
b
+
l
o
g
a
∗
(
a
)
=b+log^{*}_{a}(a)
=b+loga∗(a)
=
b
+
1
+
l
o
g
a
∗
(
1
)
=b+1+log^{*}_{a}(1)
=b+1+loga∗(1)
=
b
+
1
−
1
=b+1-1
=b+1−1
=
b
=b
=b
于是该问题就转化为求这个幂塔函数
a
共
b
个
a
a
a
a
.
.
.
a
m
o
d
a^{a^{a^{a^{...^{a}}}}}_{_{_{共b个a}}} mod
a共b个aaaa...amod
m
m
m的结果。
因为
1
≤
a
≤
1
e
6
1≤a≤1e6
1≤a≤1e6,
0
≤
b
≤
1
e
6
0≤b≤1e6
0≤b≤1e6,
1
≤
m
≤
1
e
6
1≤m≤1e6
1≤m≤1e6,暴力算法直接超出范围,队友赛后用
p
y
t
h
o
n
python
python纯暴力算到超时,因此考虑新的策略。
我们可以先处理简单的情况:
a
b
m
o
d
m
,
b
a^b\ mod\ m,b
ab mod m,b是个很大的数字,如果可以处理的话就可以递归解决问题。
这里就要请出本题的主角:欧拉降幂。
欧拉降幂
首先,我们有费马小定理
a
p
−
1
≡
1
a^{p-1}\equiv 1
ap−1≡1
(
m
o
d
p
)
,
(
g
c
d
(
a
,
p
)
=
1
)
(mod\ p),(gcd(a,p)=1)
(mod p),(gcd(a,p)=1)。
又因为
φ
(
p
)
=
p
−
1
(
p
∈
p
r
i
m
e
)
φ(p)=p-1(p∈prime)
φ(p)=p−1(p∈prime),因此我们有
a
φ
(
p
)
≡
1
(
m
o
d
p
)
,
(
g
c
d
(
a
,
p
)
=
1
)
a^{φ(p)}\equiv 1(mod \ p),(gcd(a,p)=1)
aφ(p)≡1(mod p),(gcd(a,p)=1)。
所以
a
b
≡
a
b
m
o
d
φ
(
p
)
(
m
o
d
p
)
a^b\equiv a^{b\ modφ(p)}(mod p)
ab≡ab modφ(p)(modp),我们称之为 欧拉降幂 。
但在本题中,
g
c
d
(
a
,
p
)
gcd(a,p)
gcd(a,p)不一定为
1
1
1,因此我们引入扩展欧拉降幂。
扩展欧拉降幂
首先我们给出结论
以下是证明,可以选择性跳过毕竟会用就行 。
当
b
<
φ
(
p
)
b<φ(p)
b<φ(p)时易知。
当
b
≥
φ
(
p
)
b\geq φ(p)
b≥φ(p)时证明如下:
( 以下证明内容来自 scau_bi 的CN博客 https://www.cnblogs.com/bibibi/p/10269051.html)
首先我们证明一个引理。
引理:对于
m
m
m的一个质数因子
p
p
p,有
p
c
=
p
c
m
o
d
φ
(
m
)
+
φ
(
m
)
(
m
o
d
m
)
p^c=p^{c\ mod φ(m)+φ(m)}(mod\ m)
pc=pc modφ(m)+φ(m)(mod m)
证:
我们设
m
=
s
∗
p
r
,
g
c
d
(
s
,
p
)
=
1
m=s*p^{r},gcd(s,p)=1
m=s∗pr,gcd(s,p)=1
有
p
φ
(
s
)
≡
1
(
m
o
d
p^{φ(s)}\equiv1(mod
pφ(s)≡1(mod
s
)
,
g
c
d
(
s
,
p
)
=
1
s),gcd(s,p)=1
s),gcd(s,p)=1(费马小定理)
因为
φ
(
m
)
=
φ
(
s
)
∗
φ
(
p
r
)
φ(m)=φ(s)*φ(p^{r})
φ(m)=φ(s)∗φ(pr)(
φ
φ
φ是积性函数,即
φ
(
i
)
φ
(
j
)
=
φ
(
i
∗
j
)
φ(i)φ(j)=φ(i*j)
φ(i)φ(j)=φ(i∗j))
故
p
φ
(
m
)
=
p
φ
(
s
)
φ
(
p
r
)
≡
1
φ
(
p
r
)
≡
1
(
m
o
d
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
+
1
p^{φ(m)}=k*s+1
pφ(m)=k∗s+1
两边同乘
p
r
p^r
pr,得
p
φ
(
m
)
+
r
=
k
∗
s
∗
p
r
+
p
r
=
k
∗
m
+
p
r
p^{φ(m)+r}=k*s*p^r+p^r=k*m+p^r
pφ(m)+r=k∗s∗pr+pr=k∗m+pr
所以
p
φ
(
m
)
+
r
≡
p
r
(
m
o
d
m
)
p^{φ(m)+r}\equiv p^r(mod\ m)
pφ(m)+r≡pr(mod m)
于是我们可以把这个式子推广,得到
p
k
∗
φ
(
m
)
+
r
≡
p
r
(
m
o
d
m
)
(
k
≥
0
)
p^{k*φ(m)+r}\equiv p^r(mod\ m)(k\geq 0)
pk∗φ(m)+r≡pr(mod m)(k≥0)--------------------(①)
又因为
φ
(
m
)
φ(m)
φ(m)
=
φ
(
s
)
∗
φ
(
p
r
)
=φ(s)*φ(p^r)
=φ(s)∗φ(pr)
≥
φ
(
p
r
)
\geqφ(p^r)
≥φ(pr)
=
(
p
−
1
)
∗
p
r
−
1
=(p-1)*p^{r-1}
=(p−1)∗pr−1(因为对于
p
r
p^r
pr,除了
p
p
p的倍数以外都与其互质,因此
φ
(
p
r
)
=
p
r
−
p
r
−
1
=
(
p
−
1
)
∗
p
r
−
1
φ(p^r)=p^r-p^{r-1}=(p-1)*p^{r-1}
φ(pr)=pr−pr−1=(p−1)∗pr−1)
≥
r
\geq r
≥r
(这一步的证明:
p
=
2
p=2
p=2时可以用导数易得其成立。
p
>
2
p>2
p>2时
(
p
−
1
)
∗
p
r
−
1
≥
(
p
−
1
)
∗
e
r
−
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
(p−1)∗pr−1≥(p−1)∗er−1≥(p−1)∗(r−1+1)=(p−1)∗r≥r。
这里利用了
e
x
≥
x
+
1
这
个
性
质
e^x\geq x+1这个性质
ex≥x+1这个性质,因为
x
+
1
x+1
x+1是
e
x
在
(
0
,
1
)
的
切
线
方
程
e^x在(0,1)的切线方程
ex在(0,1)的切线方程 )
因此
p
c
(
c
≥
r
)
p^c(c \geq r)
pc(c≥r)
≡
p
c
−
r
+
r
(
m
o
d
m
)
\equiv p^{c-r+r}(mod\ m)
≡pc−r+r(mod m)
≡
p
c
−
r
∗
p
r
(
m
o
d
m
)
\equiv p^{c-r}*p^r(mod\ m)
≡pc−r∗pr(mod m)
≡
p
c
−
r
∗
p
r
+
φ
(
m
)
(
m
o
d
m
)
\equiv p^{c-r}*p^{r+φ(m)}(mod\ m)
≡pc−r∗pr+φ(m)(mod m)
≡
p
c
+
φ
(
m
)
(
m
o
d
m
)
(
c
≥
r
)
\equiv p^{c+φ(m)}(mod\ m)(c \geq r)
≡pc+φ(m)(mod m)(c≥r)
因为
c
≥
r
,
r
≥
φ
(
m
)
c\geq r,r\geq φ(m)
c≥r,r≥φ(m),故
c
≥
φ
(
m
)
c\geqφ(m)
c≥φ(m)
那我们利用①式得到
p
c
+
φ
(
m
)
≡
p
c
m
o
d
φ
(
m
)
+
φ
(
m
)
(
m
o
d
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)--------------------(②)
而对于
p
k
c
p^{k^c}
pkc,我们也可以通过②式有
p
k
c
≡
p
k
c
≡
p
φ
(
m
)
+
k
c
≡
(
p
k
)
c
+
φ
(
m
)
≡
(
p
k
)
c
m
o
d
φ
(
m
)
+
φ
(
m
)
(
m
o
d
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)
pkc≡pkc≡pφ(m)+kc≡(pk)c+φ(m)≡(pk)c modφ(m)+φ(m)(mod m)
因此,我们把一个任意数
a
a
a拆成
p
1
a
1
p
2
a
2
.
.
.
p
k
a
k
p_{1}^{a_{1}}p_{2}^{a_{2}}...p_{k}^{a_{k}}
p1a1p2a2...pkak,则相乘后可以得到
a
c
≡
a
c
m
o
d
φ
(
m
)
+
φ
(
m
)
(
m
o
d
m
)
,
(
c
≥
φ
(
m
)
)
a^c\equiv a^{c\ modφ(m)+φ(m)}(mod\ m),(c\geqφ(m))
ac≡ac modφ(m)+φ(m)(mod m),(c≥φ(m))
终于证毕。建议想学懂原理的读者自行手推一遍!
好,有了解决的办法,我们就考虑递归写一个函数
f
(
b
,
p
)
f(b,p)
f(b,p),
b
b
b为递归的层数,
p
p
p是当前的模数。
每一次都利用快速幂实现
a
f
(
b
−
1
,
φ
(
p
)
)
(
m
o
d
p
)
a^{f(b-1,φ(p))}(mod\ p)
af(b−1,φ(p))(mod p)的调用。到最后一层返回
a
a
a或者
a
m
o
d
φ
(
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…,主要还是菜。
除了从外到内的递归法外,这题其实还可以从内到外来做,不容易错,有兴趣的读者可以尝试。
当然,这题也可以推广到更一般的问题:求
x
1
x
2
.
.
.
x
n
m
o
d
m
x_1^{x_2^{...^{x_n}}}mod\ m
x1x2...xnmod m,只要将上面的代码微调即可。
最后的最后,感谢一波赛后蔡队一针见血的指点。CSLNB!
DrGilbert 2019.9.2