BZOJ3884 上帝与集合的正确用法(欧拉函数)

【题解】

函数y = 2^x mod p 当p是奇数时,由于 2^φ(p) mod p = 1 ,所以函数会出现循环节长度为φ(p)的循环*(不一定是最小循环)

当p是偶数时,设 p = 2^k * q,q为奇数,函数会出现循环节长度为φ(q)的循环

所以有:

( 2^2^2…^2 ) mod p = [ 2^(2^2…^2-k) *2^k ] mod (2^k*q) ,q为奇数
                                    = 2^k * [ 2^(2^2…^2-k) mod q ]
                                    = 2^k * [ 2^[(2^2…^2-k)modφ(q)] mod q ]
                                    = 2^k * [ 2^[ ( 2^2…^2 modφ(q) - k modφ(q) ) modφ(q) ] mod q ]

其中,( 2^2…^2 ) modφ(q) 与 ( 2^2^2…^2 ) mod p 形式相同,且φ(q)<p,即模数在不断减小,直到1或2^k为止,因此可以递归求出答案


【代码】

#include<stdio.h>
#include<stdlib.h>
typedef long long LL;
int er[35]={0};
int phi(int n)
{
	int i,ans=n;
	for(i=2;i*i<=n;i++)
	{
		if(n%i==0) ans=ans/i*(i-1);
		while(n%i==0) n/=i;
	}
	if(n>1) ans=ans/n*(n-1);
	return ans;
}
LL ksm(int n,LL mod)
{
	LL ans;
	if(n==0) return 1;
	if(n==1) return 2;
	ans=ksm(n/2,mod);
	ans=ans*ans;
	if(n%2==1) ans*=2;
	return ans%mod;
}
int dfs(int p)
{
	int k,t;
	for(k=0;p%2==0;p/=2)
		k++;
	if(p==1) return 0;
	t=phi(p);
	return er[k]*(int)ksm( (dfs(t)-k%t+t)%t , (LL)p );
}
int main()
{
	int T,p,i;
	er[0]=1;
	for(i=1;i<=30;i++)
		er[i]=2*er[i-1];
	scanf("%d",&T);
	for(;T>0;T--)
	{
		scanf("%d",&p);
		printf("%d\n",dfs(p));
	}
	return 0;
}


你可能感兴趣的:(欧拉函数,无穷,欧拉定理,循环节)