高次同余方程 专题

大牛详解算法

不过cxlove大牛的写法不是hash表实现(读书少,说错了请指正),弱渣用hash表实现了一下。。。。。

hdu 2815 mod tree http://acm.hdu.edu.cn/showproblem.php?pid=2815 几个坑点:输出can‘t上面的确是全角,不是半角,手残手动改成了半角。。。。。还有一个地方就是余数n的值应该小于mod的值。。。。。

/**************************************************************
    Problem:hdu 2815
    User: youmi
    Language: C++
    Result: Accepted
    Time:62MS
    Memory:2764K
****************************************************************/
//#pragma comment(linker, "/STACK:1024000000,1024000000")
//#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <cmath>
#include <queue>
#include <deque>
#include <string>
#include <vector>
#define zeros(a) memset(a,0,sizeof(a))
#define ones(a) memset(a,-1,sizeof(a))
#define sc(a) scanf("%d",&a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define scs(a) scanf("%s",a)
#define sclld(a) scanf("%I64d",&a)
#define pt(a) printf("%d\n",a)
#define ptlld(a) printf("%I64d\n",a)
#define rep0(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define rep_1(i,n) for(int i=n;i>=1;i--)
#define rep_0(i,n) for(int i=n-1;i>=0;i--)
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define lson (step<<1)
#define rson (lson+1)
#define esp 1e-6
#define oo 0x3fffffff
#define TEST cout<<"*************************"<<endl

using namespace std;
typedef long long ll;

int n,p,b;
const int seed=65535;
struct Hh
{
    int id,next;
    ll val;
}hs[seed<<1];
bool flag[seed<<1];
int top;
void ins(int id,ll val)
{
    int k=val&seed;
    if(flag[k]==false)
    {
        flag[k]=true;
        hs[k].next=-1;
        hs[k].id=id;
        hs[k].val=val;
        return ;
    }
    while(hs[k].next!=-1)
    {
        if(hs[k].val==val)
            return ;
        k=hs[k].next;
    }
    hs[k].next=++top;
    hs[top].next=-1;
    hs[top].id=id;
    hs[top].val=val;
}
int get_find(ll val)
{
    int k=val&seed;
    if(flag[k]==false)
        return -1;
    while(k!=-1)
    {
        if(hs[k].val==val)
            return hs[k].id;
        k=hs[k].next;
    }
    return -1;
}
ll q_mul(ll a,ll b,ll mod)
{
    ll res=0;
    a=a%mod;
    while(b)
    {
        if(b&1)
            res=(res+a)%mod;
        b>>=1;
        a=(a<<1)%mod;
    }
    return res;
}
ll q_pow(ll a,ll b,ll mod)
{
    ll res=1;
    a=a%mod;
    while(b)
    {
        if(b&1)
            res=q_mul(res,a,mod);
        b>>=1;
        a=q_mul(a,a,mod);
    }
    return res;
}
ll ex_gcd(ll a,ll b,ll &x,ll &y)
{
    if(b==0)
    {
        x=1,y=0;
        return a;
    }
    ll ans=ex_gcd(b,a%b,x,y);
    ll temp=x;
    x=y;
    y=temp-y*(a/b);
    return ans;
}
ll inval(ll a)
{
    ll x,y;
    ex_gcd(a,p,x,y);
    return (x*n%p+p)%p;
}
ll babystep()
{
    top=seed;
    ll buf=1%p;
    ll D=buf,temp,x,y;
    int d=0;
    for(int i=0;i<=100;buf=buf*b%p,i++)
        if(buf==n)
            return i;
    while((temp=ex_gcd(b,p,x,y))!=1)
    {
        if(n%temp)
            return -1;
        ++d;
        p/=temp,n/=temp;
        D=D*(b/temp)%p;
    }
    int m=(int)ceil(sqrt((double)p));
    buf=1%p;
    for(int i=0;i<=m;buf=buf*b%p,i++)
        ins(i,buf);
    ll bm=q_pow(b,m,p);
    for(int i=0;i<=m;i++,D=D*bm%p)
    {
        temp=inval(D);
        int w;
        if(temp>=0&&(w=get_find(temp))!=-1)
            return i*m+w+d;
    }
    return -1;
}
int main()
{
    //freopen("in.txt","r",stdin);
    while(~sc3(b,p,n))
    {
        if(n>=p)
        {
            puts("Orz,I can’t find D!");
            continue;
        }
        zeros(flag);
        n%=p;
        ll pos=babystep();
        if(pos==-1)
            puts("Orz,I can’t find D!");
        else
            printf("%I64d\n",pos);
    }
    return 0;
}
时间: 2024-10-29 19:06:28

高次同余方程 专题的相关文章

数论之高次同余方程(Baby Step Giant Step + 拓展BSGS)

什么叫高次同余方程?说白了就是解决这样一个问题: A^x=B(mod C),求最小的x值. baby step giant step算法 题目条件:C是素数(事实上,A与C互质就可以.为什么?在BSGS算法中是要求a^m在%c条件下的逆元的,如果a.c不互质根本就没有逆元.) 如果x有解,那么0<=x<C,为什么? 我们可以回忆一下欧拉定理: 对于c是素数的情况,φ(c)=c-1 那么既然我们知道a^0=1,a^φ(c)=1(在%c的条件下).那么0~φ(c)必定是一个循环节(不一定是最小的)

高次同余方程模板BabyStep-GiantStep

/************************************* ---高次同余方程模板BabyStep-GiantStep--- 输入:对于方程A^x=B(mod C),调用BabyStep(A,B,C),(0<=A,B,C<=10^9) 输出:无解放回-1,有解放回最小非负整数x 复杂度:O(C^0.5),只与C有关,与A,B的大小无关 ************************************/ typedef long long ll; #define HAS

POJ2417 Discrete Logging【高次同余方程】

题目链接: http://poj.org/problem?id=2417 题目大意: 已知整数P.B.N满足公式B^i = N(mod P),求i的值是多少. 思路: 典型的解高次同余方程A^x = B(mod C),直接套模板解决.注意输入顺序:C A B AC代码: #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cmath>

高次同余方程 $BSGS$

第一篇\(Blog\)... 还是决定把\(luogu\)上的那篇搬过来了. BSGS,又名北上广深 它可以用来求\(a^x \equiv b (mod \ n)\)这个同余方程的一个解,其中\(a,n\)互质. 欧拉定理告诉我们,这里\(a^{\varphi(n)} \equiv 1 (mod \ n)\) 由于\(a^0 \equiv 1 (mod \ n)\),所以这里\(x\)到\(\varphi(n)\)后\(a^x \ mod \ n\)就开始循环了. 所以我们最坏情况就是\(n\)

【hdu2815-Mod Tree】高次同余方程-拓展BadyStepGaintStep

http://acm.hdu.edu.cn/showproblem.php?pid=2815 题意:裸题... 题解:又有一个坑,就是N>=P的时候输出无解. 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<cmath> 6 #include<algorithm> 7 using namespac

【poj3243-Clever Y】高次同余方程-拓展BabyStepGiantStep

http://poj.org/problem?id=3243 题意:给定X,Z,K,求一个最小的Y满足XY mod Z = K. 题解:BSGS的拓展版本(因为X和Z不一定互质).这道题挺坑的,如果K>=Z不是输出无解而是让K%=Z. 算是BSGS的模板题,我打了两种版本,就是二分查找和hash.对比两次提交来看,二分省空间,耗时间:Hash省时间,耗空间. 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstrin

HDU2815 Mod Tree【高次同余方程】

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2815 题目大意: 有一颗树,每个节点有K个儿子,那么问题来了:能否算出这棵树的最小深度D,使得这个深度 的节点数对P取模的结果为N吗? 思路: 转换一下题目含义,就变成了解K^i = N(mod P),典型的A^i = B(mod C)问题,此题B的范围 明显在[0,C-1]之间,若不在此区间,方程显然无解. AC代码: #include<iostream> #include<algori

POJ3243 Clever Y【高次同余方程】

题目链接: http://poj.org/problem?id=3243 题目大意: 已知公式A^x mod C= B,以及A.C.B的值,求解x的值为多少. 思路: 典型的求解方程A^x = B(mod C),直接模板解决. AC代码: #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cmath> #define LL __in

同余方程,不定方程总结

听说这是数论中比较重要的部分了,一点点的总结吧.. 一.线性同余方程与不定方程: 单个一元线性方程 求解方法:扩展欧几里得 exgcd 模板: long long exgcd(long long a,long long b,long long &x,long long &y) { if(!b) { x=1; y=0; return a; } __int64 tt=exgcd(b,a%b,x,y); __int64 t; t=x; x=y; y=(t-a/b*y); return tt; }