P4139 上帝与集合的正确用法
考虑扩展欧拉定理:
(a^bequiv egin{cases}a^{bmod varphi(p)+varphi(p)}& (bge varphi(p))\ a^b & (b<varphi(p))end{cases}pmod p)
对于本题,(2^{2^{2^{cdots}}}) 的指数 (b=2^{2^{cdots}}) ,显然足够大
故 (2^{2^{2^{cdots}}}equiv 2^{2^{2^{cdots}}mod varphi(p)+varphi(p)}pmod p)
指数上的 (2^{2^{cdots}}mod varphi(p)) 也同理,可以一直递归算下去
因为 (varphi(p)<p) ,所以最终模数一定会降至 (1) ,此时即可停止递归
事实上,考虑小于 (p) 的任意数 (i) ,有 (gcd(i,p)=gcd(p-i,p))
所以 (i) 和 (p-i) 要么同时与 (p) 互质,要么同时与 (p) 不互质
易证对任意 (p>2) , (varphi(p)) 必为偶数
(varphi(p)) 含有因子 (2) ,因此 (varphi(varphi(p))ledfrac12varphi(p))
所以 (varphi(p)) 是指数级递减的,递归层数为 (O(log p)) 级别
所以直接这样写就可以了
时间复杂度为 (O(p+Tlog^2p)) (线性筛预处理 (varphi) )或 (O(Tsqrt plog p+Tlog^2p)) (暴力算 (varphi) )
第一种显然稳过 第二种其实完全跑不满 也可以轻松AC
#include<stdio.h>
int T,cnt,t,p,s,i,a[50];
int phi(int x) {
for (s=x,i=2; i*i<=x; ++i)
if (x%i==0) {
s=s/i*(i-1);
while (x%i==0) x/=i;
}
return x>1&&(s=s/x*(x-1)),s;
}
int power(int x,int y,int p) {
for (s=1; y; y>>=1)
(y&1)&&(s=1ll*s*x%p),x=1ll*x*x%p;
return s+p;
}
int main() {
for (scanf("%d",&T); T; --T) {
scanf("%d",&p),cnt=0,t=1;
if (p==1) { puts("0"); continue; }
while (p>1) a[++cnt]=p,p=phi(p);
for (i=cnt; i; --i) t=power(2,t,a[i]);
printf("%d
",t%a[1]);
}
return 0;
}
CF906D Power Tower
看起来像是用某种很牛b的数据结构维护(?)
但再想想就发现这题也是用个扩欧就行了
这次的幂运算是有限次的 其实比无限的麻烦一点 要加点细节
时间复杂度为 (O(n+sqrt plog p+qlog^2p))
#include<stdio.h>
typedef long long ll;
int n,m,q,l,r,cnt,s,i,p[40],a[100010];
inline int mod(ll x,int p) { return (x<p?x:x%p+p); }
inline int power(int x,int y,int p) {
for (s=1; y; y>>=1)
(y&1)&&(s=mod(1ll*s*x,p)),x=mod(1ll*x*x,p);
return s;
}
int phi(int x) {
for (s=x,i=2; i*i<=x; ++i) if (x%i==0) {
s=s/i*(i-1);
while (x%i==0) x/=i;
}
return x>1&&(s=s/x*(x-1)),s;
}
int f(int i,int r,int x) {
if (x>cnt) return 1;
if (i==r) return mod(a[i],p[x]);
return power(a[i],f(i+1,r,x+1),p[x]);
}
int main() {
scanf("%d%d",&n,&m),p[1]=1;
while (m>1) p[++cnt]=m,m=phi(m);
for (i=1; i<=n; ++i) scanf("%d",a+i);
for (scanf("%d",&q); q; --q)
scanf("%d%d",&l,&r),
printf("%d
",f(l,r,1)%p[1]);
return 0;
}