• 【51nod 1038】X^A Mod P


    题目描述

    X^A mod P = B,其中P为质数。给出P和A B,求< P的所有X。
    例如:P = 11,A = 3,B = 5。
    3^3 Mod 11 = 5
    所有数据中,解的数量不超过Sqrt(P)。

    分析

    这道题包括几个知识点

    离散对数(大步小步BSGS算法)

    求关于x的同余方程(y^x equiv n pmod{P}(P为质数))的解,
    (m=lceil sqrt{n} ceil,x=bm+r),我们预处理出(y^i(iin[0,P-1])),用map或hash储存起来
    我们从小到大枚举b,就可以根据(y^{(b+1)m} cdot n^{-1} equiv y^{m-r}pmod{P}),在有序表中找到(y^{m-r})来的到指数r

    N次剩余

    求关于x的同余方程(x^y equiv n pmod{P}(P为质数))的解
    设P的原根为g,因为(varphi(P)=P-1),根据原根的性质({1,2,3...P-1})一一与({g^1,g^2,g^3...g^{P-1}})对应
    (x=g^s,n=g^t)
    通过BSGS,我们可以求出t,
    于是(s cdot y equiv t pmod{P-1}),用扩展欧几里得解方程。

    #include <cmath>
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <map>
    #include <bitset>
    #include <set>
    #include <vector>
    const int inf=2147483647;
    const int mo=1e6+7;
    const int N=100005;
    using namespace std;
    struct arr{  
        long long x,id;  
        bool operator<(const arr &b)const{  
            if (x == b.x) return id < b.id;  
            return x<b.x;  
        }  
    }E[100500]; 
    int T;
    long long sol[N],P,A,B,G,m,num,ans[N],d[N];
    long long ksm(long long x,long long y)
    {
    	long long s=1;
    	for(;y;y>>=1,x=x*x%P)
    		if(y&1) s=s*x%P;
    	return s;
    }
    bool check(int G)
    {
    	int tmp=P-1;
    	for(int i=2;i*i<=tmp;i++)
    	{
    		if(tmp%i) continue;
    		if(ksm(G,i)==1 || ksm(G,tmp/i)==1) return false;
    	}
    	return true;
    }
    void pre()
    {
    	for(G=2;!check(G);G++);
    	m=ceil(sqrt(P));
    	long long v=1;
    	for(int i=0;i<=m;i++)
    	{
    		arr tmp;
    		tmp.x=v,tmp.id=i;
    		E[i]=tmp;
    		v=v*G%P;
    	}
    	sort(E,E+m);
    }
    long long BSGS(long long y)
    {
    	long long ny=ksm(y,P-2),sum=1,s=ksm(G,m);
    	for(int i=0;i<m;i++)
    	{
    		long long val=(sum=sum*s%P)*ny%P;
            arr tmp;
            tmp.x=val,tmp.id=-1;
            long long pos=lower_bound(E,E+m+1,tmp)-E;
    		if(E[pos].x==val) return i*m+m-E[pos].id;
    	}
    	return 0;
    }
    int exgcd(int a,int b,int &x,int &y)
    {
    	if(!b)
    	{
    		x=1,y=0;
    		return a;
    	}
    	long long r=exgcd(b,a%b,y,x);
    	y-=x*(a/b);
    	return r;
    }
    void residue(long long a,long long b,long long m)
    {
    	int x=0,y=0,d=exgcd(a,m,x,y);
    	if(b%d) return;
    	num=d;
    	sol[0]=x*(b/d)%m;
    	for(int i=1;i<d;i++) sol[i]=(sol[i-1]+m/d)%m;
    	for(int i=0;i<d;i++) sol[i]=(sol[i]+m)%m;
    }
    void solve()
    {
    	pre();
    	num=0,residue(A,BSGS(B),P-1);
    	if(!num) printf("No Solution
    ");
    	else
    	{
    		for(int i=0;i<num;i++) ans[i]=ksm(G,sol[i]);
    		sort(ans,ans+num);
    		for(int i=0;i<num;i++) printf("%lld ",ans[i]);
    		putchar('
    ');
    	}
    }
    int main()
    {
    	for(scanf("%d",&T);T--;)
    	{
    		scanf("%lld%lld%lld",&P,&A,&B);
    		solve();
    	}
    }
    
  • 相关阅读:
    【简单算法】27.验证二叉搜索树
    【简单算法】26. 二叉树的最大深度
    【简单算法】25. 环形链表
    pandas 数据处理
    主成分分析 PCA
    hive 导出数据到本地
    深度学习的优化方法 总结
    ALS算法 (面试准备)
    Bagging和Boosting的区别(面试准备)
    ROC 曲线,以及AUC计算方式
  • 原文地址:https://www.cnblogs.com/chen1352/p/9102565.html
Copyright © 2020-2023  润新知