N次剩余(详解+例题+代码)

来源:互联网 发布:淘宝企业店营业执照 编辑:程序博客网 时间:2024/06/14 05:20
从《国际大学生程序设计大赛算法与实现》中所学
任务:
给定N, a, p, 求出(x^N)%p=a 在模p意义下的所有解x。
说明:
令g为p的原根,因为p为素数,所以phi(p)=p-1。
由原根的性质得:
如果g为p的原根,则:g^i mod p != g^j mod p (p为素数), 其中i != j且i, j介於1至(p-1)之间
所以,可以设g^y=x, g^t=a,则有:
g^(y*N)%p=g^t
又由原根的性质:
g^(y*N)%p=g^t -> (y*N)%(p-1)=t (此方程可以由拓展欧几里得解)
另外g^t=a可以由离散对数求出
给定newx, k, m, 方程 (x^k)%m=newx, 求在模m意义下的所有解x。
限制:
0 <= newx, m, k <= 1.5*10^15; m是素数。
/*hdu 3930  题意:  给定newx, k, m, 方程 (x^k)%m=newx, 求在模m意义下的所有解x。  限制:  0 <= newx, m, k <= 1.5*10^15; m是素数。  思路:  N次剩余 */#include <iostream>#include <cstdio>#include <cmath>#include <cstring>#include <vector>#include <algorithm>using namespace std;#define LL __int64#define PB push_backLL mul(LL a,LL b,LL m){    LL ret = 0;    a %= m;    while(b){        if(b & 1) ret = (ret + a) % m;        a = (a + a) % m;        b >>= 1;    }    return ret;}LL a_b_MOD_c(LL a,LL b,LL m){    LL ret = 1;    a %= m;    while(b){        if(b&1) ret = mul(ret,a,m);        a = mul(a,a,m);        b >>= 1;    }    return ret;}LL ext_gcd(LL a,LL b,LL &x,LL &y){    if(b==0) { x=1, y=0; return a; }    LL ret= ext_gcd(b,a%b,y,x);    y-= a/b*x;    return ret;}vector<LL> a;bool g_test(LL g,LL p){    for(LL i=0;i<a.size();++i)        if(a_b_MOD_c(g,(p-1)/a[i],p)==1)            return 0;    return 1;}LL pri_root(LL p){    a.clear();    LL tmp=p-1;    for(LL i=2;i<=tmp/i;++i)        if(tmp%i==0){            a.push_back(i);            while(tmp%i==0)                tmp/=i;        }    if(tmp!=1)        a.push_back(tmp);    LL g=1;    while(true){        if(g_test(g,p))            return g;        ++g;    }}const int HASH_MOD=9876543;LL key[HASH_MOD], val[HASH_MOD];int head[HASH_MOD], next[HASH_MOD];struct Hash{    int tot;    void init(){        memset(head, -1, sizeof(head));        tot = 0;    }    LL insert(LL x, LL y){        int k = x % HASH_MOD;        key[tot] = x;        val[tot] = y;        next[tot] = head[k];        head[k] = tot++;    }    LL find(LL x){        int k = x % HASH_MOD;        for(int i = head[k]; i != -1; i = next[i])            if(key[i] == x)                return val[i];        return -1;    }}hs;//求解模方程a^x=b(mod m),n为素数,无解返回-1  //注意:要求0 < a < m; 0 <= b < m; 否则按题意自己转化。//复杂度O(sqrt(m))LL log_mod(LL a, LL b, LL m){    hs.init();    LL s = ceil(sqrt(m + 0.5));    LL cur = 1;    for (int i = 0; i < s; ++i){        if(hs.find(cur)==-1) hs.insert(cur,i);    //记得先判重,在插入        cur = cur * a % m;    }    LL v = a_b_MOD_c(a, (m - s - 1 + m) % m, m);    for(int i = 0; i < s; ++i){        LL tmp = hs.find(b);        if(tmp!=-1)            return s * i + tmp;        b=b*v%m;    }    return -1;}/*n次剩余  任务:  给定N, a, p, 求出(x^N)%p=a 在模p意义下的所有解x。  说明:  令g为p的原根,因为p为素数,所以phi(p)=p-1。  由原根的性质得:  如果g为p的原根,则:g^i mod p != g^j mod p (p为素数), 其中i != j且i, j介於1至(p-1)之间  所以,可以设g^y=x, g^t=a,则有:  g^(y*N)%p=g^t  又由原根的性质:  g^(y*N)%p=g^t -> (y*N)%(p-1)=t (此方程可以由拓展欧几里得解)  另外g^t=a可以由离散对数求出 */vector<LL> residue(LL p, LL N, LL a){    LL g = pri_root(p);g %= p;    LL m = log_mod(g, a, p);    vector<LL> ret;    if(a == 0){        ret.PB(0);        return ret;    }    if(m == -1)        return ret;    LL A = N, B = p - 1, C = m, x, y;    LL d = ext_gcd(A, B, x, y);    if(C % d != 0) return ret;    x = x * (C / d) % B;    LL delta = B / d;    for(int i = 0; i < d; ++i){        x = ((x + delta) % B + B) % B;        ret.PB(a_b_MOD_c(g, x, p));    }    sort(ret.begin(), ret.end());    ret.erase(unique(ret.begin(), ret.end()), ret.end());    return ret;}int main(){    int cas = 0;    LL k,m,newx;    while(scanf("%I64d%I64d%I64d",&k, &m, &newx)!=EOF){        vector<LL> ans;        ans = residue(m,k,newx);        printf("case%d:\n",++cas);        if(ans.size()==0) puts("-1");        for(int i = 0; i < ans.size(); ++i)            printf("%I64d\n",ans[i]);    }    return 0;}


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 商铺门口有电杆怎么办 漏电保护器坏了怎么办 空开进线烧了怎么办 过压保护灯亮怎么办 美的热水器接地异常怎么办 欠压保护器坏了怎么办 三孔插座没地线怎么办 二胡琴筒裂缝宽怎么办 有了月亮从四星宠满级的怎么办 党委下属没有党支部了党委怎么办 发生日期大于制单日期怎么办 美的空调出现p0怎么办 薯片受潮不脆了怎么办 泡过的莲子煮不烂怎么办 绿豆有煮不熟的怎么办 吃了羊肉吃西瓜怎么办 吃了狗肉和绿豆怎么办 做的衣柜没有门怎么办 蒸馒头熟了会瘪怎么办 3dmax贴图太大了怎么办 嘴皮边缘颜色深怎么办 嘴巴周围肤色暗沉怎么办 中奖彩票被洗了怎么办 牙龈下面长米粒肉疙瘩怎么办 书画印章盖反了怎么办 金龙鱼一个月不吃东西怎么办 罗汉鱼头撞扁了怎么办 房顶开槽埋线白色不一样怎么办 顶上灯挪位置线怎么办 马蜂窝弄掉又来怎么办 蜂窝弄掉又有怎么办 2018年小龙虾底板脏怎么办 一本分数线擦边过怎么办 玩具塑料球扁了怎么办 胶皮与海绵开了怎么办 安卓不支持flash了怎么办 看视频要加载flash怎么办 下水道管子铁皮破了怎么办 炸金花牌一样大怎么办 玩棋牌游戏输了怎么办 苹果7插耳机外放怎么办