poj3243 Clever Y

5 篇文章 0 订阅

http://www.elijahqi.win/archives/3022
Description

Little Y finds there is a very interesting formula in mathematics:

XY mod Z = K

Given X, Y, Z, we all know how to figure out K fast. However, given X, Z, K, could you figure out Y fast?

Input

Input data consists of no more than 20 test cases. For each test case, there would be only one line containing 3 integers X, Z, K (0 ≤ X, Z, K ≤ 109).
Input file ends with 3 zeros separated by spaces.
Output

For each test case output one line. Write “No Solution” (without quotes) if you cannot find a feasible Y (0 ≤ Y < Z). Otherwise output the minimum Y you find.
Sample Input

5 58 33
2 4 3
0 0 0
Sample Output

9
No Solution
Source

POJ Monthly–2007.07.08, Guo, Huayang
别人再明白讲的再清楚也要自己推导明白才好。不能因为自己智商低为借口抄代码 考虑到一般的bsgs我们都会了(其实blog主是最辣鸡的! 考虑做题遇到的最多的限制条件是什么 是p为质数 那么为什么这么做呢因为保证有逆元如果没有呢 没有这个条件满足 axb(modp) a x ≡ b ( m o d p ) 只要gcd(a,p)=1 直接做也是即可的只不过枚举只需要枚举0~ φ(p)1 φ ( p ) − 1 即可 那加入这两个条件均不满足怎么办那先把原始式转化一下比如a,p共同有一个公因子g 那么我可以用将原式替换一下 设A*d=a那么其他元素同理可以写成 Agax1Bg(mod Cg) A ∗ g ∗ a x − 1 ≡ B ∗ g ( m o d   C ∗ g ) 那么两边同时去掉一个g 即可变成 Aax1B(mod C) A ∗ a x − 1 ≡ B ( m o d   C ) 那么很好一直这样递归做下去知道a与C互质 同时记录一下一个nm表示我用掉了几个a 然后将前面的A用一个变量类乘起来辣鸡博主用mul 然后 一直到最后一定有个终止状态即g=1 最后的方程可以写成 mulaxnmb(mod c) m u l ∗ a x − n m ≡ b ( m o d   c ) 不妨和普通的bsgs一样假设x=i*m+j+nm好了显然这样的话我没有 办法判断系数<=nm的情况 这样的话提前判断一下即可 因为每次求gcd至少/2所以最多Log次运算即可 还有一些小细节 比如求新的bsgs的这个公式的时候这个mul始终保留在左边 然后因为这种情况下只是满足gcd(a,c)=1所以求逆元的时候需要使用欧拉定理来求注意不要直接用费马小定理即可 其他细节见辣鸡elijahqi的代码

#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
inline char gc(){
    static char now[1<<16],*S,*T;
    if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=gc();}
    while(ch<='9'&&ch>='0') x=x*10+ch-'0',ch=gc();
    return x*f;
}
const int md=1e5+3;
struct node{int x,id,next;}hs[md];int h[md],num;
inline void init(){num=0;memset(h,0,sizeof(h));}
inline void insert1(int x,int id){static int tmp;tmp=x%md;
    for (int i=h[tmp];i;i=hs[i].next) if (hs[i].x==x) return;
    hs[++num]=(node){x,id,h[tmp]};h[tmp]=num;
}
inline int query(int x){static int tmp;tmp=x%md;
    for (int i=h[tmp];i;i=hs[i].next) if (hs[i].x==x) return hs[i].id;
    return -1;
}
inline int gcd(int x,int y){return y?gcd(y,x%y):x;}
inline int phi(int x){
    if (x==1) return 1;int tmp=x;
    for (int i=2;i*i<=x;++i){
        if (x%i) continue;tmp-=tmp/i;
        while(x%i==0) x/=i;
    }if(x>1) tmp-=tmp/x;return tmp;
}
inline int ksm(ll b,int t,int p){static ll tmp;tmp=1;
    for (;t;(b*=b)%=p,t>>=1) if(t&1) (tmp*=b)%=p;return tmp;
}
inline int exbsgs(int a,int b,int mod){static ll mul,tmp;static int nm,inva;
    if (!a) return !b?0:-1;ll aa=1;
    for (int i=0;i<=30;++i) {if (aa==b) return i;aa*=a;}
    int g=gcd(a,mod);mul=1;nm=0;
    while(g!=1){
        if (b%g) return -1;(mul*=a/g)%=mod;++nm;
        b/=g;mod/=g;g=gcd(a,mod);
    }init();static ll tmp1;int m=ceil(sqrt(mod));tmp=b;
    tmp1=ksm(a,m,mod);inva=ksm(a,phi(mod)-1,mod);
    for (int i=0;i<m;++i) 
    insert1(tmp,i),(tmp*=inva)%=mod;tmp=mul;
    for (int i=0;i<=m;++i){
        int j=query(tmp);
        if (j!=-1) {return i*m+j+nm;break;}(tmp*=tmp1)%=mod;
    } return -1;
}
int x,z,k;
int main(){
    freopen("poj3243.in","r",stdin);
    while(1) {x=read();z=read();k=read();
        if (!x&&!z&&!k) break;
        x%=z;k%=z;int tmp=exbsgs(x,k,z);
        tmp==-1?puts("No Solution"):printf("%d\n",tmp);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值