[上帝与集合的正确用法]

P4139

上帝与集合的正确用法

题目描述

定义a0 = 1 , an = 2an1 , 可以证明bn = an (mod p) 在某项之后都是同一个值,求这个值

做法

f(p)=222... mod p,当b>ϕ(p)时有欧拉降幂公式:ab  a(b mod ϕ(p)) + ϕ(p) (mod p)
f(p)=222... mod p , f(ϕ(p))=222... mod ϕ(p)(将 p 替换为 ϕ(p) 代入f(p)
f(p)=2f(ϕ(p)+ϕ(p) mod p ,时间复杂度为 p 一直进行 ϕ(p) 操作,直到 ϕ(1)=0
根据唯一分解定理,p=p1k1×p2k2×p3k3...×pnkn,pi , ϕ(p)=p×(11p1)×(11p2)×(11p3)...×(11pn)ϕ(ϕ(p))12p,故复杂度为log(p)级别

code

#include <cstdio>
#include <iostream>
typedef long long LL;
using namespace std;
const int maxn = 1e7+6;
int phi[maxn],prime[maxn],cnt; 
bool check[maxn];

int quickpower(LL a,int b,int p)
{
	LL res = 1;
	while(b)
	{
		if(b & 1)
			res = res * a % p;
		a = a * a % p;
		b >>= 1;
	}
	return res;
}

int f(int p)
{
	if(p == 1) return 0;
	return quickpower(2,f(phi[p])+phi[p],p);
}

int main()
{
	int T;
	scanf("%d",&T);
	for(int i=2;i<=maxn;i++)
    {
        if(!check[i])
        {
            phi[i] = i - 1;
            prime[++cnt] = i;
        }
        for(int j=1;j<=cnt;j++)
        {
            if(prime[j] * i > maxn) break;
            check[i*prime[j]] = 1;
            if(!(i%prime[j]))
            {
                phi[i*prime[j]] = prime[j] * phi[i];
                break;
            }
            else phi[i*prime[j]] = phi[i] * phi[prime[j]];
        }
    }
	while(T --)
	{
		int p;
		scanf("%d",&p);
		printf("%d\n",f(p));
	}
	return 0;
}
posted @   风丨铃  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示