1467: Pku3243 clever Y
Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 254 Solved: 142
[ Submit][ Status][ Discuss]
Description
小Y发现,数学中有一个很有趣的式子: X^Y mod Z = K 给出X、Y、Z,我们都知道如何很快的计算K。但是如果给出X、Z、K,你是否知道如何快速的计算Y呢?
Input
本题由多组数据(不超过20组),每组测试数据包含一行三个整数X、Z、K(0 <= X, Z, K <= 109)。 输入文件一行由三个空格隔开的0结尾。
Output
对于每组数据:如果无解则输出一行No Solution,否则输出一行一个整数Y(0 <= Y < Z),使得其满足XY mod Z = K,如果有多个解输出最小的一个Y。
Sample Input
5 58 33
2 4 3
0 0 0
2 4 3
0 0 0
Sample Output
9
No Solution
No Solution
HINT
Source
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<bitset>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
typedef long long LL;
const int Mod = 999983;
struct data{
int Num,val; data(){}
data(int Num,int val): Num(Num),val(val){}
};
stack <int> s;
vector <data> v[Mod];
int Mul(const LL &x,const LL &y,const LL &p) {return x * y % p;}
int ksm(int x,int y,int p)
{
int ret = 1;
for (; y; y >>= 1)
{
if (y & 1) ret = Mul(ret,x,p);
x = Mul(x,x,p);
}
return ret;
}
void Extend_Gcd(LL a,LL &x,LL b,LL &y,LL &g)
{
if (!b) {g = a; x = 1; y = 0; return;}
Extend_Gcd(b,y,a % b,x,g); y -= a / b * x;
}
int GetInv(int a,int p)
{
LL x,y,g;
Extend_Gcd(a,x,p,y,g);
return (x % p + p) % p;
}
void Clear()
{
while (!s.empty())
v[s.top()].clear(),s.pop();
}
void Insert(int val,int Num)
{
int pos = val % Mod;
if (!v[pos].size()) s.push(pos);
for (int i = 0; i < v[pos].size(); i++)
if (v[pos][i].val == val) return;
v[pos].push_back(data(Num,val));
}
int Search(int val)
{
int pos = val % Mod;
for (int i = 0; i < v[pos].size(); i++)
if (v[pos][i].val == val) return v[pos][i].Num;
return -1;
}
void BSGS(int y,int p,int z)
{
Clear(); LL x,Y,g,tmp = 1;
int cnt = 0,_p = p; y %= p; z %= p;
if (y == z) {puts("1"); return;}
if (z == 1) {puts("0"); return;} //ÌØÅÐAns == 1 || Ans == 0
for (;;)
{
Extend_Gcd(y,x,_p,Y,g);
if (g == 1) break; ++cnt;
if (z % g != 0) {puts("No Solution"); return;}
tmp = Mul(tmp,y / g,p); z /= g; _p /= g;
}
p = _p; tmp = GetInv(tmp,p); z = Mul(z,tmp,p);
int Sqrt = sqrt(p); tmp = ksm(y,Sqrt,p);
for (int now = 1 % p,tot = 0; tot <= Sqrt; now = Mul(now,y,p),tot++) Insert(now,tot); //×¢ÒâÄ£Êý¿ÉÄÜΪ1£¬ËùÒÔÆðʼµãÊÇ1 %£ð
for (int i = 0,now = 1; i <= Sqrt + 3; now = Mul(now,tmp,p),i++) // ö¾Ù´ÎÊýÂÔ´óÓÚSqrt
{
int Inv = GetInv(now,p);
int ret = Search(Mul(Inv,z,p));
if (ret == -1) continue;
printf("%d\n",i * Sqrt + ret + cnt); return;
}
puts("No Solution");
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
for (;;)
{
int x,z,k; scanf("%d%d%d",&x,&z,&k);
if (!x && !z && !k) break;
if (!z) {puts("No Solution"); continue;}
if (!x) {puts(!k ? "0" : "No Solution"); continue;}
BSGS(x,z,k);
}
return 0;
}