Description
原始问题:给出A,B,X,NA,B,X,NA,B,X,N和一个素数PPP,令f(X)=AX+Bf(X)=AX+Bf(X)=AX+B,计算fN(X) mod Pf^N(X)\ mod\ PfN(X) mod P
逆问题:给出X,N,TX,N,TX,N,T和一个素数PPP,找非负整数A,BA,BA,B使得1≤A≤p−1,0≤B≤p−11\le A\le p-1,0\le B\le p-11≤A≤p−1,0≤B≤p−1使得f(X)N mod P=Tf(X)^N\ mod\ P=Tf(X)N mod P=T
逆问题的逆问题:给出一整数MMM,找X,N,T,PX,N,T,PX,N,T,P满足1≤X≤109,1≤N≤1018,0≤T<P≤M1\le X\le 10^9,1\le N\le 10^{18},0\le T<P\le M1≤X≤109,1≤N≤1018,0≤T<P≤M且g(X,N,T,P)g(X,N,T,P)g(X,N,T,P)最大,其中g(X,N,T,P)g(X,N,T,P)g(X,N,T,P)为AAA的最小值使得其满足:存在BBB使得1≤A≤p−1,0≤B≤p−11\le A\le p-1,0\le B\le p-11≤A≤p−1,0≤B≤p−1使得f(X)N mod P=Tf(X)^N\ mod\ P=Tf(X)N mod P=T,如果无解则g(X,N,T,P)=−1g(X,N,T,P)=-1g(X,N,T,P)=−1.
Input
一个整数M(3≤M≤105)M(3\le M\le 10^5)M(3≤M≤105)
Output
输出四个整数X,N,T,PX,N,T,PX,N,T,P
Sample Input
8
Sample Output
2018 231 1 7
Solution
首先考虑已知A,B,X,P,NA,B,X,P,NA,B,X,P,N时TTT的值,由矩阵快速幂可知T=fN(X)=(ANX+(1+A+...+AN−1)B)%PT=f^N(X)=(A^NX+(1+A+...+A^{N-1})B)\% PT=fN(X)=(ANX+(1+A+...+AN−1)B)%P
假设A>1A>1A>1,此时即判断T−ANX≡AN−1A−1B mod PT-A^NX\equiv \frac{A^N-1}{A-1}B\ mod\ PT−ANX≡A−1AN−1B mod P是否有解,不妨令T=1,X=PT=1,X=PT=1,X=P,那么只要AN−1̸≡0 mod PA^N-1\not \equiv 0\ mod\ PAN−1̸≡0 mod P则BBB有解,显然可以取A=2,N=5,P=3A=2,N=5,P=3A=2,N=5,P=3使得该同余不等式成立,故该方程一定有A>1A>1A>1的解
为使AAA最大,我们有xN≡1 mod P,2≤x<Ax^N\equiv 1\ mod\ P,2\le x<AxN≡1 mod P,2≤x<A且AN̸≡1 mod PA^N\not\equiv 1\ mod\ PAN̸≡1 mod P,满足前一个条件只需取N=lcm(r(2),...,r(A−1))N=lcm(r(2),...,r(A-1))N=lcm(r(2),...,r(A−1))即可,其中r(x)r(x)r(x)为使得xg≡1 mod Px^g\equiv 1\ mod\ Pxg≡1 mod P的最小正整数ggg,满足第二个条件只需让(P−1)̸∣N(P-1)\not|N(P−1)̸∣N即可,故直接枚举PPP和AAA即可,注意若N<PN<PN<P把NNN乘上PPP即可,因为(P,P−1)=1(P,P-1)=1(P,P−1)=1
Code
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
#define maxn 100005
vector<int>f[maxn],prime;
bool mark[maxn];
void init(int n=1e5)
{
for(int i=2;i<=n;i++)
if(!mark[i])
{
prime.push_back(i);
for(int j=2*i;j<=n;j+=i)mark[j]=1;
}
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j+=i)
f[j].push_back(i);
}
int mul(int a,int b,int c)
{
ll z=1ll*a*b;
return z-z/c*c;
}
int Pow(int a,int b,int c)
{
int ans=1;
while(b)
{
if(b&1)ans=mul(ans,a,c);
a=mul(a,a,c);
b>>=1;
}
return ans;
}
ll gcd(ll a,ll b)
{
return b?gcd(b,a%b):a;
}
ll lcm(ll a,ll b)
{
return a/gcd(a,b)*b;
}
ll res[maxn];
int main()
{
init();
int m;
scanf("%d",&m);
int ma=0,ansp;
for(int i=0;i<prime.size()&&prime[i]<=m;i++)
{
int p=prime[i];
ll lc=1;
res[p]=lc;
for(int r=2;r<p;r++)
{
int ans=p-1;
for(int j=0;j<f[p-1].size();j++)
if(Pow(r,f[p-1][j],p)==1)
{
ans=f[p-1][j];
break;
}
lc=lcm(lc,ans);
if(lc%(p-1)==0)
{
if(r>ma)ma=r,ansp=p;
break;
}
else res[p]=lc;
}
}
if(res[ansp]<ansp)res[ansp]*=ansp;
printf("%d %lld 1 %d\n",ansp,res[ansp],ansp);
return 0;
}