zoukankan      html  css  js  c++  java
  • 题解-洛谷P4139 上帝与集合的正确用法

    上帝与集合的正确用法

    (T) 组数据,每次给定 (p),求

    [left(2^{left(2^{left(2^{cdots} ight)} ight)} ight)mod p ]

    数据范围:(1le Tle 1000)(1le ple 10^7)


    这篇题解主要是给自己看的,因为小蒟蒻从未见过这种骚操作。


    首先这个式子虽是无限的,但是答案是固定的。

    • 先来几个引理

    [a^{varphi(p)}equiv1pmod p ]

    [a^bequiv a^{(bmod varphi(p))+varphi(p)}pmod p ]

    所以上面那个递归式可以转化:

    [2^{left(2^{left(2^{cdots} ight)} ight)}equiv 2^{left(2^{left(2^{cdots} ight)}modvarphi(p) ight)+varphi(p)}pmod p ]

    所以可以先求 (left(2^{left(2^{left(2^{cdots} ight)} ight)} ight)mod varphi(p)),又可以先求 (left(2^{left(2^{left(2^{cdots} ight)} ight)} ight)mod varphi(varphi(p)))……最终一直递归下去。

    [ecause egin{cases} varphi(1)=1\ varphi(p)<p&p>1\ end{cases}\ herefore varphi(varphi(varphi(cdotsvarphi(p)cdots)))=1\ ]

    因为 (left(2^{left(2^{left(2^{cdots} ight)} ight)} ight)mod 1=0),所以递归有边界了,可以开码了。


    时间复杂度 (Theta({ m max}p+Tlog^2 p))


    • 代码:
    #include <bits/stdc++.h>
    using namespace std;
    
    //Start
    typedef long long ll;
    typedef double db;
    #define mp(a,b) make_pair(a,b)
    #define x(a) a.first
    #define y(a) a.second
    #define b(a) a.begin()
    #define e(a) a.end()
    #define sz(a) int((a).size())
    #define pb(a) push_back(a)
    const int inf=0x3f3f3f3f;
    const ll INF=0x3f3f3f3f3f3f3f3f;
    
    //Data
    const int N=1e7;
    
    //Sieve
    bitset<N+7> np;
    int phi[N+7];
    vector<int> pr;
    void Sieve(){
    	np[1]=phi[1]=1;
    	for(int i=2;i<=N;i++){
    		if(!np[i]) pr.pb(i),phi[i]=i-1;
    		for(int p:pr)if(i*p<=N){
    			np[i*p]=1;
    			if(i%p==0){phi[i*p]=phi[i]*p;break;}
    			phi[i*p]=phi[i]*phi[p];
    		} else break;
    	}
    } 
    
    //Pow
    int Pow(int a,int x,int mod){
    	if(a==0) return 0; int res=1;
    	for(;x;a=1ll*a*a%mod,x>>=1)if(x&1) res=1ll*res*a%mod;
    	return res;
    }
    int Jump(int p){ // 两行核心代码
    	if(p==1) return 0;
    	return Pow(2,Jump(phi[p])+phi[p],p); 
    }
    
    //Main
    int main(){
    	int t; scanf("%d",&t);
    	Sieve();
    	for(int ti=1;ti<=t;ti++){
    		int p; scanf("%d",&p);
    		printf("%d
    ",Jump(p));
    	}
    	return 0;
    }
    

    祝大家学习愉快!

  • 相关阅读:
    一条Sql的Spark之旅
    Redis学习笔记:Redis在C#中的使用
    MySQL_表操作
    git上传新项目到coding
    Jenkins 安装 on centos7
    day 36
    表单生成器(Form Builder)之表单数据存储结构mongodb篇
    ORA-16032和ORA-07286 LOG_ARCHIVE_DEST_1没生效
    SQL查询小案例
    mysql从5.6升级到5.7后出现 Expression #1 of ORDER BY clause is not in SELECT list,this is incompatible with DISTINCT
  • 原文地址:https://www.cnblogs.com/Wendigo/p/12876403.html
Copyright © 2011-2022 走看看