【EX_BSGS】BZOJ1467 Pku3243 clever Y

1467: Pku3243 clever Y

Time Limit: 4 Sec  Memory Limit: 64 MB
Submit: 425  Solved: 238
[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

Sample Output

9
No Solution

题解

EX_BSGS模板题

思路懒得写了

代码

//by 减维
#include<set>
#include<map>
#include<queue>
#include<ctime>
#include<cmath>
#include<bitset>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define il inline
#define rg register
#define db double
#define mpr make_pair
#define maxn
#define inf (1<<30)
#define eps 1e-8
#define pi 3.1415926535897932384626L
using namespace std;

inline int read()
{
    int ret=0;bool fla=0;char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-'){fla=1;ch=getchar();}
    while(ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();}
    return fla?-ret:ret;
}

ll x,y,p;
map<ll,ll> mp;

ll gcd(ll x,ll y){return y==0?x:gcd(y,x%y);}

ll ksm(ll x,ll y,ll p)
{
    ll ret=1;x%=p;
    for(;y;y>>=1,x=x*x%p)
        if(y&1) ret=ret*x%p;
    return ret;
}

ll exbsgs(ll x,ll y,ll p)
{
    x%=p;y%=p;
    if(!x&&!y) return 1;
    if(y==1) return 0;
    if(!x) return -1;
    ll t,d=1,k=0;
    while((t=gcd(p,x))!=1)
    {
        if(y%t) return -1;
        y/=t,p/=t,d=d*x/t%p,k++;
        if(d==y) return k;
    }
    mp.clear();
    ll m=sqrt(p+0.5);
    ll o=y;
    for(int i=0;i<=m;++i,o=o*x%p)
        if(!mp.count(o)) mp[o]=i;
    ll tmp=ksm(x,m,p);
    for(int i=1;i<=m;++i)
    {
        d=d*tmp%p;
        if(mp.count(d)) return ((i*m-mp[d])%p+k+p)%p;
    }
    return -1;
}

int main()
{
    while(1)
    {
        scanf("%lld%lld%lld",&x,&p,&y);
        if(!x&&!y&&!p) break;
        ll ans=exbsgs(x,y,p);
        if(ans==-1) printf("No Solution\n");
        else printf("%lld\n",ans);
    }
    return 0;
}

 

posted @ 2018-03-16 15:06  减维  阅读(162)  评论(0编辑  收藏  举报