• 洛谷P4139 上帝与集合的正确用法 & CF906D Power Tower


    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;
    }
    
  • 相关阅读:
    Java Concurrency
    Java Annotation,Java注解
    Think in java, notes
    嵌套事务
    java dynamic proxy,动态代理
    埃里克·雷蒙德
    HDU1222 Wolf and Rabbit
    HUT1098 素MM
    HDU1568 Fibonacci
    HDU1501 Zipper DFS+记忆化搜索
  • 原文地址:https://www.cnblogs.com/REKonib/p/15054474.html
Copyright © 2020-2023  润新知