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

时间:2022-11-18 23:14:29

快来和数论愉快玩♂耍啊23333

先证欧拉定理:若$(a,m)=1$,则$a^{\varphi(m)}\equiv1(\text{mod }m)$(证明来自《初等数论》)

取所有在$[1,m-1]$中与$m$互质的数$x_{1\cdots\varphi(m)}$,因为对$\forall i,j$有$x_i\not\equiv x_j(\text{mod }m)$,所以$ax_i\not\equiv ax_j(\text{mod }m)$,又因为$(ax_i,m)=1$,所以$x_{1\cdots n}$与$ax_{1\cdots n}$之间存在一一对应的模$m$同余关系

$\begin{align*}\prod\limits_{i=1}^{\varphi(m)}x_i\equiv\prod\limits_{i=1}^{\varphi(m)}ax_i\equiv a^{\varphi(m)}\prod\limits_{i=1}^{\varphi(m)}x_i(\text{mod }m)\end{align*}$

因为$(x_i,m)=1$,所以我们得到$a^{\varphi(m)}\equiv1(\text{mod }m)$

然后是所谓的“扩展欧拉定理”:若$x\geq\varphi(m)$,则$a^x\equiv a^{x\text{ mod }\varphi(m)+\varphi(m)}(\text{mod }m)$(证明来自这篇文章

一个要用到的引理是对任意质数$p$和$q\gt1$有$\varphi(p^q)\geq q$,用归纳法证明:对$q$归纳,假设$\varphi(p^q)\geq q$,那么$\varphi(p^{q+1})=p\varphi(p^q)\geq pq\geq q+1$

先证$m=p^q$的情况,其中$p$是质数

①若$(a,p)=1$,可直接用欧拉定理证明

②若$(a,p)=p$,那么$a=pt$,$a^x\equiv(pt)^x$,因为$x\geq \varphi(p^q)\geq q$,所以$a^x\equiv0(\text{mod }p^q)$,同理可得$a^{x\text{ mod }\varphi(m)+\varphi(m)}\equiv0(\text{mod }p^q)$

对于一般的$\begin{align*}m=\prod\limits_{i=1}^kp_k^{q_k}\end{align*}$,对每个$p_i^{q_i}$,我们都有$a^x\equiv a^{x\text{ mod }\varphi(p_i^{q_i})+\varphi(p_i^{q_i})}(\text{mod }p_i^{q_i})$

首先我们有$\varphi(p_i^{q_i})|\varphi(m)$,所以$a^{x\text{ mod }\varphi(m)+\varphi(m)}=a^{x+j\varphi(p_i^{q_i})}$,又有$a^{x\text{ mod }\varphi(p_i^{q_i})+\varphi(p_i^{q_i})}=a^{x+k\varphi(p_i^{q_i})}$,此时如果$p_i|a$,那么两个式子都模$p_i^{q_i}$余$0$,否则$(a,p_i)=1$,套用欧拉定理立得$a^{x\text{ mod }\varphi(p_i^{q_i})+\varphi(p_i^{q_i})}\equiv a^{x\text{ mod }\varphi(m)+\varphi(m)}(\text{mod }p_i^{q_i})$,即$a^x\equiv a^{x\text{ mod }\varphi(m)+\varphi(m)}(\text{mod }p_i^{q_i})$,直接合并所有质因数可以得到$a^x\equiv a^{x\text{ mod }\varphi(m)+\varphi(m)}(\text{mod }m)$,于是我们证明了扩展欧拉定理

然后来做这题,设$f(p)$表示题目中无限个$2$对$p$取模的值,那么$f(1)=0,f(p)\equiv2^{f(\varphi(p))+\varphi(p)}(\text{mod }p)$

然后就做完了(雾

#include<stdio.h>
typedef long long ll;
const int T=10000000;
int pr[10000010],phi[10000010];
bool np[10000010];
void sieve(){
	int i,j,M;
	M=0;
	phi[1]=1;
	for(i=2;i<=T;i++){
		if(!np[i]){
			M++;
			pr[M]=i;
			phi[i]=i-1;
		}
		for(j=1;j<=M;j++){
			if(pr[j]*(ll)i>T)break;
			np[i*pr[j]]=1;
			if(i%pr[j]==0){
				phi[i*pr[j]]=phi[i]*pr[j];
				break;
			}
			phi[i*pr[j]]=phi[i]*(pr[j]-1);
		}
	}
}
int pow(int a,int b,int p){
	int s=1;
	while(b){
		if(b&1)s=s*(ll)a%p;
		a=a*(ll)a%p;
		b>>=1;
	}
	return s;
}
int f(int p){
	if(p==1)return 0;
	return pow(2,f(phi[p])+phi[p],p);
}
int main(){
	sieve();
	int T,p;
	scanf("%d",&T);
	while(T--){
		scanf("%d",&p);
		printf("%d\n",f(p));
	}
}