方法: BSGS
解析:
大爷讲完BSGS,太神辣orz。
这些数论刷的要死要活的。
这是一道裸BSGS问题。
求方程A^x=B(mod C)的最小非负整数x。
暴枚是不可以都通过的,其次它是多组数据,所以怎么想呢。
我们不妨把整个问题分成两半,对于前一半,我们把值先算出来扔到哈希表里,然后后一半再找其能够凑成答案的值是否在哈希表中,如果在哈希表中,则第一个被找的一定是最小的。
这个算法还是很好懂的,C是质数的话也好分析也好写。
代码:
using namespace std;
typedef long long ll;
int head[mod+10];
ll c,a,b,ans;
int cnt;
struct node
{
int from,to,next;
ll val;
}edge[mod+10];
ll get_inv(ll x,ll y)
{
ll ret=1;
while(y)
{
if(y&1)ret=(ret*x)%c;
x=(x*x)%c;
y>>=1;
}
return ret;
}
void init()
{
memset(head,-1,sizeof(head));
cnt=1;
}
void edgeadd(int from,int to,ll val)
{
edge[cnt].from=from,edge[cnt].to=to,edge[cnt].val=val;
edge[cnt].next=head[from];
head[from]=cnt++;
}
void BSGS(int A,int B,int C)
{
//A^x=B(mod C);
int m=(int)ceil(sqrt(C));
ll k=1;
edgeadd(1,0,1);
for(int i=1;i<m;i++)
{
k=(k*A)%C;
int flag=0;
for(int j=head[k%mod];j!=-1;j=edge[j].next)
{
int val=edge[j].val;
if(val==k){flag=1;break;}
}
if(!flag)edgeadd(k%mod,i,k);
}
k=(k*A)%C;
ll D=1;
ll inv=get_inv(D,C-2);
ll tmp=B*inv%C;
ans=-1;
for(int j=head[tmp%mod];j!=-1;j=edge[j].next)
{
int val=edge[j].val;
if(val==tmp)
{
ans=edge[j].to;break;
}
}
if(ans!=-1){printf("%lld\n",ans);return;}
for(int i=1;i<=m;i++)
{
D=D*k%C;
inv=get_inv(D,C-2);
tmp=B*inv%C;
for(int j=head[tmp%mod];j!=-1;j=edge[j].next)
{
int val=edge[j].val;
if(val==tmp)
{
ans=edge[j].to+i*m;
break;
}
}
if(ans!=-1){printf("%lld\n",ans);return;}
}
}
int main()
{
while(~scanf("%lld%lld%lld",&c,&a,&b))
{
init();
BSGS(a,b,c);
if(ans==-1)puts("no solution");
}
}