SPOJ MOD - Power Modulo Inverted

来源:互联网 发布:淘宝什么商品销量排行 编辑:程序博客网 时间:2024/05/17 07:34

题目链接:http://www.spoj.com/problems/MOD/ (POJ 3243双倍经验)

Description

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.
[题目大意]求最小的y使得k ≡ xy (mod 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. (以三个0结束输入)

Output

For each test case, output one line with the answer, or “No Solution”(without quotes) if such an integer doesn’t exist.

Sample Input

5 58 33
2 4 3
0 0 0

Sample Output

9
No Solution


Solution

此题为扩展BSGS(Baby Steps Giant Steps)模板题

普通BSGS

对于AxB(modC)
令m=c+1
则原式可变为Aimj,其中i,j[1,m]
移项后得AimBAj(modC)
从1~m枚举j,把BAjmodC扔进哈希表里
然后从1~m枚举i,看看Aim在不在哈希表里。如果在,则im-j即为答案;如果枚举完所有i后仍没找到过,则无解

以上是普通BSGS的流程,只适用于gcd(A,C)=1的情况,这是因为在从①变化至②的过程中,如果Aj在mod C下的逆元不存在,就无法从推出结果的②推回原式①,则求出的“答案”并非真正答案

扩展BSGS

AxB(modC)
由取模定义可得
Ax=kC+B
g=gcd(A,C),则有
Axg=kCg+Bg
AxgBg(modCg)
AgAx1Bg(modCg)
如果g不为B的因数的话,显然无解
B=BgC=Cg,重复执行以上消掉gcd的步骤,直到gcd(A,C)=1

这时,原式已变为
DAxcntB(modC)
cnt为执行了消除gcd步骤的次数,D为历次Ag之积
现在执行普通的BSGS,将结果加上cnt即为答案

不过,有一点要注意,如果答案在[0,cnt-1]内,BSGS可能会给出错误的答案。此时只需要先暴力扫一遍答案是否可能在[0,cnt-1]内就行了,因为cnt最多只能到log(n),时间完全不虚


Code

这里写图片描述

#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>using namespace std;#define N 100000#define mod 99991#define foru(i,l,r) for (int i=l; i<=r; i++)#define setmem(a,x) memset(a,x,sizeof(a))typedef long long LL;int val[N],id[N],stk[N],top;LL x,y,g;int gethash(int x) {return x%mod;}void insert(int x, int y){    int h=gethash(x);    while (val[h]!=-1&&val[h]!=x) h=(h+1)%mod;    val[h]=x, id[h]=y;    stk[++top]=h;}int get(int x){    int h=gethash(x);    while (val[h]!=-1&&val[h]!=x) h=(h+1)%mod;    if (val[h]==-1) return -1;    return id[h];}void clear(){    for (; top; top--) val[stk[top]]=-1;}int gcd(int a, int b){    return !b? a: gcd(b,a%b);}int bsgs(int A, int B, int C, LL D){    LL m=ceil(sqrt(C)), am=1;    clear();    foru(i,1,m)    {        am=(am*A)%C;        insert(am*B%C,i);    }    foru(i,1,m)    {        D=D*am%C;        int j=get(D);        if (j!=-1) return i*m-j;    }    return -1;}int exbsbg(int a, int b, int c){    LL x=1%c, d=1, g, cnt=0;//c=1的情况要小心    foru(i,0,100)    {        if (x==b) return i;        x=x*a%c;    }    while ((g=gcd(a,c))!=1)    {        if (b%g!=0) return -1;        b/=g, c/=g;        d=d*(a/g)%c, cnt++;    }    int ans=bsgs(a,b,c,d);    if (ans==-1) return -1;    else return ans+cnt;}int main(){    setmem(val,-1);    int x,z,k;    while (scanf("%d%d%d",&x,&z,&k)!=EOF&&(x|z|k))    {        int ans=exbsbg(x%z,k%z,z);        if (ans==-1) puts("No Solution");        else printf("%d\n",ans);    }    return 0;}
0 0
原创粉丝点击