因不知起什么标题所以就看看这个标题到底可以起多长但现在看来它真的可以取特别长可能可以把这一整行写满吧但到底什么情况下才会需要起这么长一个标题又不是人人都像我一样无聊但也说不定早就有人试过它的上限了但毕竟实践出真知我还是试试它怎么还能写这上限有点太大了吧究竟是谁才会起这么长的标题啊真的很影响观感算了也是照顾特殊用户了没准人家的标题真的需要很长它既然它这么定了那肯定是有它的意义好了上限200个字符不谢
题目描述
给你一个数\(p\),缩减剩余系是指由\([1,p]\)之间的与\(p\)互质的整数组成的集合。现在给你一个数\(x\),求在模\(p\)意义下\(x\)的幂集有多少个不同的值,(形如\(1,x,x^2,x^3,\)...的数叫做\(x\)的幂集)
输入格式
第一行一个数\(T\)表示测试组数
之后\(T\)行,每一行有两个数\(p\)和\(x\),表示给定的模数和元。
输出格式
一共输出\(T\)行,表示答案
数据范围
\(1\le p\le 10^8,T\le500,保证p,x互质\)。
显然这道题就是让我们找到最小的正整数\(t\)使\(x^t\equiv1\pmod p\)
根据欧拉定理我们知道: \(当\gcd(a,p)=1时有a^{\varphi(p)} \equiv 1 \pmod p\)
但\(\varphi(p)不一定是最小的t\),不过肯定有\(t\mid\varphi(p)\)。(严格的证明本蒟蒻不会)
所以只要枚举\(\varphi(p)\)的因数进行验证就好啦,复杂度约\(\Theta(T\sqrt p)\),但其实实际会比这快很多。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
long long p,x,T,phi,ans;
void getphi(long long n,long long &a)
{
a=1;
for(long long i=2;i*i<=n;i++)
{
if(n%i)
continue;
a*=i-1,n/=i;
while(n%i==0)
n/=i,a*=i;
}
if(n>1)
a*=n-1;
}
long long fm(long long bot,long long pow,long long MOD)
{
long long s=1;
for(;pow;pow>>=1,bot=bot*bot%MOD)
if(pow&1)
s=s*bot%MOD;
return s;
}
void getans(long long n)
{
for(long long i=1;i*i<=n;i++)
{
if(n%i)
continue;
if(fm(x,i,p)==1)
{
ans=i;
break;
}
if(i*i<n&&fm(x,n/i,p)==1)
ans=n/i;
}
}
int main()
{
scanf("%lld",&T);
while(T--)
{
scanf("%lld %lld",&p,&x);
getphi(p,phi);
getans(phi);
printf("%lld\n",ans);
}
return 0;
}
浙公网安备 33010602011771号