题意:求K个素数pi对应的ni。ni满足:ni,ni^2,ni^3,...,ni^m对pi取模各不相同(i=1,2,3,...),且m最大,ni最大。
理论基础: 原根的定义:首先,对于互质的两个整数a,m。必然存在:d<=m-1,使得:a^d=1(mod m),比如说:d=phi(m)。我们定义a对m的阶为所有满足a^d=1(mod m)的d中最小的一个正整数。如此一来,如果a对m的阶为phi(m),那么我们称a为m一个原根。
原根性质定理:如果a为m的原根,记它的阶为ord,那么:a,a^2,a^3,...,a^ord对m取模的值各不相同。
定理1:对于整数a,与素数m,则a,a^m对m取模的结果相同(费马小定理)。
定理2:可以证明,如果正整数(a,m)=1和正整数 d 满足a^d=1(mod m),则ord整除d。
定理:如果p为素数,那么素数p一定存在原根,并且p的原根的个数为phi(p-1).
设m是正整数,a是整数,若a模m的阶等于φ(m),则称a为模m的一个原根.
假设一个数g对于P来说是原根,那么g^i mod P的结果两两不同,且有 1<g<P, 0<i<P,那么g可以称为是P的一个原根,归根到底就是g^(P-1) = 1 (mod P)当且
仅当指数为P-1的时候成立.(这里P是素数).
求原根目前的做法只能是从2开始枚举,然后暴力判断g^(P-1) = 1 (mod P)是否当且当指数为P-1的时候成立。而由于原根一般都不大,所以可以暴力得到.
求一个奇素数的所有原根方法。
设g是P的平方非剩余,是P-1的标准分解式,若恒有
成立,
则g就是P的原根。
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define maxn 70000
bool isprime[maxn];
int prime[maxn],nprime;
void getprime()
{
long long i,j;
memset(isprime,1,sizeof(isprime));
nprime=0;
for(i=2; i<maxn; i++)
if(isprime[i])
{
prime[nprime++]=i;
for(j=i*i; j<maxn; j+=i)isprime[j]=0;
}
}
long long exp_mod(long long a,long long b,long long c)
{
a%=c;
long long ans=1;
while(b)
{
if(b&1)ans=ans*a%c;
b>>=1,a=a*a%c;
}
return ans;
}
bool judge(int yl,int n)
{
int x=n-1;
for(int i=0; prime[i]<=x; i++)
if(x%prime[i]==0)
if(exp_mod(yl,x/prime[i],n)==1)
return 0;
return 1;
}
int main()
{
int t,n;
getprime();
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=n-1; i>0; i--)
if(judge(i,n))
{
printf("%d\n",i);
break;
}
}
return 0;
}