zoukankan      html  css  js  c++  java
  • 原根与指标

    参考资料

    一.阶

    1.定义:设(a,p)是互质整数,必定有(x)满足(a^xequiv 1pmod{p}),最小的满足条件的正整数(x)称为(a)(p)的阶,记为(Ord_p(a)),如果(gcd(a,p)!=1),则不存在阶。
    2.性质:
    <1>设(a,p)是互质整数,存在(x')满足(a^{x'}equiv 1pmod{p}),则(Ord_p(a)|x')
    <2>设(a,p)是互质整数,有(Ord_p(a)|varphi(p))(根据欧拉定理反证)。

    二.原根

    1.定义:设(a,p)为互质整数,若(Ord_p(a)=varphi(p)),则称(a)是模(p)的一个原根。
    2.性质:
    <1>只有(2,4,p^k,2*p^k)(p)是奇素数)有原根。
    <2>一个数(p)若存在原根,则它有(varphi(varphi(p)))个原根。
    <3>(a)(p)的原根,(a^0,a^1,a^2...a^{Ord_p(a)-1})(p)两两不同。即当(a)(p)的原根时,(a^0,a^1,a^2...a^{Ord_p(a)-1})构成了模(p)的简化剩余系。
    3.求一个数的原根:
    暴力:
    (2)开始暴力枚举(x),要求(gcd(x,p)=1),之后检验(x)是否为(p)的原根。
    由于(Ord_P(x)|varphi(p)),我们需要检验对于任意(d|varphi(p))(d ot=varphi(p)),是否都满足(x^d otequiv 1pmod{p})
    优化:
    由于如果(x^kequiv 1pmod{p}),则(x^{kd}equiv 1pmod{p})
    (varphi(p)=prod_{i=1}^k p_i^{c_i})
    只需要对每个(i)验证是否满足(x^{frac{varphi(p)}{p_i}} otequiv 1pmod{p}),因为(frac{varphi(p)}{p_i})是除去分解后次幂中含有(p_i^{c_i})以外的所有约数的倍数。这样就相当于判掉了所有(varphi(n))的约数。

    三.指标

    1.定义:设(g)是模(p)的一个原根,整数(a)(p)互质,则存在唯一的整数(x)满足:(g^xequiv apmod{p}),称(x)为以(g)为底对模(p)的一个指标。记为(x=ind_ga)
    2.性质:
    <1>(aequiv bpmod{p}->ind_gaequiv ind_gbpmod{varphi(p))})
    <2>(ind_g(ab)equiv ind_ga+ind_gbpmod{varphi(p)})
    <3>(ind_g(a^k)equiv k*ind_gapmod{varphi(p)})
    3.求指标:直接(BSGS)即可。

    四.N次剩余问题(转自)

    求解(x^kequiv apmod{p}),p是质数。
    先求出(p)的最小原根(g),因为p是质数,因此必定存在(ind_gx)(ind_ga)
    所求即变为(k*ind_gxequiv ind_gapmod{varphi(p)})
    (exgcd)解出即可。
    模板题
    code:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    int a,K,mod,g,t,x,y,d;
    vector<int>prime,ans;
    inline int power(int x,int k,int mod)
    {
    	int res=1;
    	while(k)
    	{
    		if(k&1)res=res*x%mod;
    		x=x*x%mod;k>>=1;
    	}
    	return res;
    }
    inline int find(int p)
    {
    	int tmp=p-1;
    	for(int i=2;i*i<=tmp;i++)
    	{
    		if(tmp%i)continue;
    		prime.push_back(i);
    		while(tmp%i==0)tmp/=i;
    	}
    	if(tmp>1)prime.push_back(tmp);
    	for(int g=1;g<=p;g++)
    	{
    		bool flag=1;
    		for(unsigned int i=0;i<prime.size();i++)
    			if(power(g,(p-1)/prime[i],p)==1){flag=0;break;}
    		if(flag)return g;
    	}
    	return -1;
    }
    inline int BSGS(int a,int b,int mod)
    {
    	if(b==1)return 0;
    	if(!a)return !b?1:-1;
        map<int,int>mp;mp.clear();
        int t=ceil(sqrt(mod));
        for(int i=0,j=1;i<=t;i++,j=j*a%mod)mp[b*j%mod]=i;
        a=power(a,t,mod);
        for(int i=1,j=a;i<=t;i++,j=j*a%mod)if(mp.count(j))return i*t-mp[j];
    	return -1;
    }
    int exgcd(int a,int b,int &x,int &y)
    {
    	if(!b){x=1,y=0;return a;}
    	int d=exgcd(b,a%b,x,y);
    	int z=x;x=y,y=z-(a/b)*y;
    	return d;
    }
    signed main()
    {
    	scanf("%lld%lld%lld",&mod,&K,&a);
    	if(!a){puts("1");puts("0");return 0;}
    	g=find(mod);t=BSGS(g,a,mod);
    	//cerr<<"test::"<<g<<' '<<t<<endl;
    	d=exgcd(K,mod-1,x,y);
    	if(t%d){puts("0");return 0;}
    	int P=(mod-1)/d;
    	x=(x*(t/d)%P+P)%P;
    	while(x<mod)
    	{
    		ans.push_back(power(g,x,mod));
    		x+=P;
    	}
    	sort(ans.begin(),ans.end());
    	printf("%lld
    ",ans.size());
    	for(int i=0;i<ans.size();i++)printf("%lld
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    CSLA服务端如何使用多线程的解决方案
    一片马蜂窝文章
    VB.NET和C#之间的语法不同比较
    [软件推荐]jQuery,JavaScript,HTML,CSS,PHP,MySQL,正则表达式 CHM帮助手册
    使用jQuery.Validate进行客户端验证
    知道AutoHotKey
    数据库设计问题
    [书籍推荐]为了自己的钱包,为了自己的时间——分享一下自己的淘书经验
    策略模式4
    SQLiteHelperSQLite帮助类
  • 原文地址:https://www.cnblogs.com/nofind/p/11933586.html
Copyright © 2011-2022 走看看