Given 3 positive integers x, y and z, you can find k = xy%z easily, by fast power-modulo algorithm. Now your task is the inverse of this algorithm. Given 3 positive integers x, z and k, find the smallest non-negative integer y, such that k%z = xy%z.
Input
About 600 test cases.
Each test case contains one line with 3 integers x, z and k.(1<= x, z, k <=109)
Input terminates by three zeroes.
Output
For each test case, output one line with the answer, or "No Solution"(without quotes) if such an integer doesn't exist.
Example
Input:
5 58 33
2 4 3
0 0 0
Output:
9
No Solution
思路:
扩展BSGS ,学习博客
自己模拟一直T,还是照着别人的学习一下吧。
下面的是ac代码,对于3 9 9 样例也能通过。
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <cmath>
using namespace std;
typedef long long ll;
//unordered_map<ll,ll> ha;
const int MOD=76543;
struct node{
ll id;
ll val;
int nex;
}Hash[MOD];
int head[MOD],tot;
void init(){
tot=0;memset(head,-1,sizeof(head));
}
void insert(ll x,int y)
{
ll k=x%MOD;
Hash[tot].id=y;
Hash[tot].val=x;
Hash[tot].nex=head[k];
head[k]=tot++;
}
ll find(ll x)//找不到返回-1
{
ll k=x%MOD;
for(int i=head[k];i!=-1;i=Hash[i].nex)
if(Hash[i].val==x)
return Hash[i].id;
return -1;
}
ll gcd(ll a, ll b) {
return !b ? a : gcd(b, a % b);
}
ll qpow(ll a,ll b,ll mod) {
ll res = 1;
while (b) {
if (b & 1) res=res*a%mod;
a=a*a%mod;
b>>= 1;
}
return res;
}
ll ebsgs(ll a, ll b, ll p) {
if (b == 1) return 0;
ll t,d = 1,k = 0;
while ((t = gcd(a, p)) != 1) {
if (b % t) return -1;
k++,b /= t,p /= t, d = (d*(a / t)) % p;
if (b == d) return k;
}
init();
//ha.clear();
ll m = ceil(sqrt(p+0.5));
ll a_m = qpow(a,m,p);
ll mul = b;
for (ll j = 1; j <= m; j++) {
mul = (mul * a) % p;
insert(mul,j);
// ha[mul] = j;
}
for (ll i = 1; i <= m; i++) {
d = (d * a_m) % p;
ll tmp=find(d);
if (tmp!=-1) return i * m - tmp + k;
}
return -1;
}
int main() {
ll a,b,p,ans;
while (~scanf("%lld%lld%lld", &a, &p, &b),a+b+p) {
ans=ebsgs(a%p, b,p);
if (ans == -1) puts("No Solution");
else printf("%lld\n",ans);
}
return 0;
}
下面这段代码有误,对于3 9 9 识别不正确,感谢网友指出。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<vector>
#define MOD 123456
using namespace std;
typedef long long ll;
const int HashMod=123456;
struct node{
struct Line{int val,id,nex;}e[100000];
int h[HashMod],cnt;
void add(int x,int y,int k)
{
e[++cnt]=(Line){x,y,h[k]};
h[k]=cnt;
}
void clear(){memset(h,-1,sizeof(h));cnt=0;}
void insert(int x,int y)
{
int k=x%HashMod;
add(x,y,k);
}
int find(int x)
{
int k=x%HashMod;
for(int i=h[k];i!=-1;i=e[i].nex)
if(e[i].val==x)
return e[i].id;
return -1;
}
}Hash;
ll qsm(ll a,ll b,ll p)
{
ll t=1;
while(b>0)
{
if(b&1)
{
t=t*a%p;
}
a=a*a%p;
b>>=1;
}
return t%p;
}
int ex_BSGS(int a,int b,int p)
{
if(b==1) return 0;
int k=0,ac=1;//ac->a^c/d;
while(1)
{
int d=__gcd(a,p);
if(d==1) break;
if(b%d) return -1;
b/=d;p/=d;k++;
ac=1ll*ac*a/d%p;
if(b==ac)return k;
}
Hash.clear();
int m=sqrt(p)+1;
ll t=b;
for(int i=0;i<m;i++){
Hash.insert(t,i);
t=t*a%p;
}
ll tt=qsm(a,m,p);
t=ac*tt%p;
for(int i=1;i<=m;i++)
{
int j=Hash.find(t);
t=t*tt%p;
if(j==-1) continue;
return i*m-j+k;
}
return -1;
}
int main()
{
int a,b,p;
while(~scanf("%d%d%d",&a,&p,&b),a+b+p)
{
int ans=ex_BSGS(a,b,p);
if(ans==-1) puts("No Solution");
else printf("%d\n",ans);
}
return 0;
}