POJ 3243 // HDU 2815(改下输出,加个判断)

A^x = B (mod C) 的模板题,不够要用扩展BSGS

(虽然AC,但完全理解不了模板0.0,以后学好数学在来慢慢理解555555)

#include <iostream>
#include <cstdio>
#include <ctime>
#include <cmath>
const int MAXN = 1000 + 10;
const int maxn = 65535;
const int INF = 0x7fffffff;
using namespace std;
typedef long long ll;
struct Hash{
       ll a,b,next;
}Hash[maxn << 1];
ll flg[maxn + 66];
ll top,idx;
void ins(ll a,ll b){
     ll k = b & maxn;
     if (flg[k] != idx){
        flg[k] = idx;
        Hash[k].next = -1;
        Hash[k].a = a;
        Hash[k].b = b;
        return ;
     }
     while (Hash[k].next != -1){
           if(Hash[k].b == b) return ;
           k = Hash[k].next;
     }
     Hash[k].next = ++ top;
     Hash[top].next = -1;
     Hash[top].a = a;
     Hash[top].b = b;
}
ll Find(ll b){
    ll k = b & maxn;
    if (flg[k] != idx) return -1;
    while (k != -1){
          if(Hash[k].b == b) return Hash[k].a;
          k = Hash[k].next;
    }
    return -1;
}
ll gcd(ll a,ll b) {return b == 0? a: gcd(b, a % b);}
ll exgcd(ll a, ll b, ll &x, ll &y){
    if (b == 0){x = 1; y = 0; return a;}
    ll tmp = exgcd(b, a % b, y, x);
    y -= x * (a / b);
    return tmp;
}
ll solve(ll a, ll b, ll c){
    ll x, y, Ans;
    ll tmp = exgcd(a, c, x, y);
    Ans = (ll)(x * b) % c;
    return Ans >= 0 ? Ans : Ans + c;
}
ll pow(ll a, ll b, ll c){
    ll ret = 1;
    while(b)
    {
        if(b & 1) ret = ret * a % c;
        a = a*a%c;
        b>>= 1;
    }
    return ret;
}
ll BSGS(ll A, ll B, ll C){
    top = maxn;
    ++idx;
    ll buf = 1 % C, D = buf, K, tmp;
    for (ll i = 0; i <= 100; i++){
        if (buf == B) return i;
        buf = (buf * A) % C;
    }
    ll d = 0;
    while ((tmp = gcd(A, C)) != 1){
          if (B % tmp != 0) return -1;
          d++;
          B /= tmp;
          C /= tmp;
          D = D * A / tmp % C;
    }
    //hash表记录1-sqrt(c)的值
    ll M = (ll)ceil(sqrt(C * 1.0));
    buf = 1 % C;
    for (ll i = 0; i <= M; i++){
        ins(i, buf);
        buf = (buf * A) % C;
    }
    K = pow(A, M, C);
    for (ll i = 0; i <= M; i++){
        tmp = solve(D, B, C);
        ll w;
        if (tmp >= 0 && (w = Find(tmp)) != -1) return i * M + w + d;
        D = (D * K) % C;
    }
    return -1;
}

int main(){

    ll A, B, C;
    while (cin >> A >> C >> B && (A || B || C)){
          B %= C;
          ll tmp = BSGS(A, B, C); // A^x = B (mod C);
          if (tmp >= 0) cout << tmp << endl;
          else cout << "No Solution\n";
    }
    return 0;
}
时间: 2025-01-04 23:30:41

POJ 3243 // HDU 2815(改下输出,加个判断)的相关文章

离散对数,giant-step baby-step,拓展giant-step baby-step (poj 2417, hdu 2815)

普通giant-step baby-step: poj 2417 题意: B^L==N(MOD P), 给出P,B,N, 求最小的非负L. 限制: 2 <= P < 2^31 && P为素数; 2 <= B <P; 1 <= N < P 思路: 离散对数,用giant-step baby-step解决. 普通giant-step baby-step过程,要求P为素数: 令s = ceil(sqrt(P)), 则L = b * s + r (0 <=

POJ 1113 || HDU 1348: wall(凸包问题)

传送门: POJ:点击打开链接 HDU:点击打开链接 下面是POJ上的题: Wall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 29121   Accepted: 9746 Description Once upon a time there was a greedy King who ordered his chief Architect to build a wall around the King's cast

POJ 2411 &amp;&amp; HDU 1400 Mondriaan&#39;s Dream (状压dp 经典题)

Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 12341   Accepted: 7204 Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series

最小生成树,POJ和HDU几道题目的解题报告(基于自己写的模板)

首先POJ题目: 链接:1251 Jungle Roads 题目大意:纯求最小生成树,结果为最小权值边的和.采用邻接表 代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <queue> 5 using namespace std; 6 7 #define maxn 30 //最大顶点个数 8 int n; //顶点数,边数 9 10 struct arcn

2014湘潭全国邀请赛I题 Intervals /POJ 3680 / 在限制次数下取有权区间使权最大/小问题(费用流)

先说POJ3680:给n个有权(权<10w)开区间(n<200),(区间最多数到10w)保证数轴上所有数最多被覆盖k次的情况下要求总权最大,输出最大权. 思路:       限制的处理:s-->开始流量为k,要求总权最大,即费用最大,所以费用取负,最小费用最大流即可.对于输入区间[a,b]:w,添加边:a-->b,流量为1,费用为-w. 对于点i,i+1,添加边,费用为0,流量无穷.显然这种处理,限制了区间最多取k次,(流量控制),跑最大流能走添加的边尽量走,且越大越好(负数刚刚是

poj 1226 hdu 1238 Substrings 求若干字符串正串及反串的最长公共子串 2002亚洲赛天津预选题

题目:http://poj.org/problem?id=1226 http://acm.hdu.edu.cn/showproblem.php?pid=1238 其实用hash+lcp可能也可以,甚至可能写起来更快,不过我没试,我最近在练习后缀数组,所以来练手 后缀数组的典型用法之一----------------后缀数组+lcp+二分 思路:1.首先将所有的字符串每读取一个,就将其反转,作为一组,假设其下标为i到j,那么cnt[i]到cnt[j]都标记为一个数字(这个数字意思是第几个读入的字符

POJ 2104&amp;HDU 2665 Kth number(主席树入门+离散化)

K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 50247   Accepted: 17101 Case Time Limit: 2000MS Description You are working for Macrohard company in data structures department. After failing your previous task about key inse

Eclipse项目发布到Tomcat下被加载两次

近来发现,Eclipse项目发布到Tomcat下被加载了两次.启动Tomcat时,项目被加载了两次,项目启动了两次. 启动tomcat会两次加载项目 原因是server.xml设置的问题. 解决方案:在右边的工程中,有一个Servers 这里有个server.xml文件,打开,观察文件最末尾, 删除Context标签.注意不要把</Host>也删了. 改后,如下所示(即还剩一个</Host>标签):

poj 2337 欧拉回路按照最小字典序输出+注意为了按最小字典序怎么处理邻接表

http://poj.org/problem?id=2337 WA了好久,昨晚1点多睡不着写的,狂WA,当时是因为用邻接矩阵存储,比如aba,aa只能存下一个,这个之前还没遇到过,今天才注意到--邻接矩阵无法存储平行边, 关于欧拉回路判断看我另几篇日志或者看我的欧拉总结 再贴个输出欧拉回路的模板 其中,参数u是起点,注意如果是输出欧拉路径的话,u必须是出度比入度大一的那个点,如果输出欧拉回路,随便按要求找个就行 void euler(int u) { for(int i=head[u];i!=-