zoukankan      html  css  js  c++  java
  • BZOJ 1420 Discrete Root

    思路:数学大汇总

    提交:(3)

    错因:有一个(j)写成(i)

    题解:

    求:(x^k equiv a mod p)
    我们先转化一下:求出(p)的原根(g)
    然后我们用(BSGS)可以求出 (g^b equiv a mod p),即(a)的指标(b).然后因为原根的幂可以表示([0,p-1])中的任何一个数,所以设(x=g^y),原式可以转化成 ((g^y)^k equiv a mod p),即(g^{y*k} equiv g^bmod P),所以指数满足 (y*k equiv b mod varphi(p)),可以用(exgcd)解出这个方程的解。

    代码:

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<map>
    #include<algorithm>
    #define ll long long
    #define RR register ll
    #define int ll
    #define R register int
    using namespace std;
    namespace Luitaryi {
    template<class I> inline I g(I& x) { x=0; register I f=1;
    	register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
    	do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*=f;
    } ll a,n,k,m,p,G,cnt,mem[100010],ind,ans[100010];
    map<ll,ll> mp;
    inline ll qpow(ll a,ll b) { RR ret=1;
    	for(;b;b>>=1,(a*=a)%=p) if(b&1) (ret*=a)%=p; return ret;
    }
    inline void exgcd(ll a,ll b,ll& x,ll& y) {
    	if(!b) {x=1,y=0; return ;} 
    	exgcd(b,a%b,y,x); y-=a/b*x; 
    }
    inline ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
    inline int BSGS() {
    	R t=sqrt(p)+1; RR sum=a;//BSGS求a的指标 
    	for(R i=1;i<=t;++i) (sum*=G)%=p,mp[sum]=i; 
    	sum=qpow(G,t); if(sum==0) return a==0?1:-1; 
    	for(R i=1;i<=t;++i) {
    		RR tmp=qpow(sum,i);
    		if(mp.count(tmp)&&i*t-mp[tmp]>=0) return i*t-mp[tmp];
    	} return -1;
    }
    inline void main() {
    	m=g(p)-1,g(k),g(a); if(!a) return (void) printf("1
    0
    "); RR x=m;
    	for(R i=2,lim=sqrt(m);i<=x&&i<=lim;++i) {
    		if(x%i==0) mem[++cnt]=i;
    		while(x%i==0) x/=i;
    	} if(x>1) mem[++cnt]=x; 
    	//求原根 
    	for(R i=2;i<=m;++i) { register bool flg=true;
    		for(R j=1;j<=cnt;++j) {
    			if(qpow(i,m/mem[j])==1) {
    				flg=false; break;
    			} 
    		} if(flg) {G=i; break;}
    	} 
    	//求指标 
    	ind=BSGS(); if(ind==-1) return (void) puts("0"); 
    	//解同余方程 
    	RR y; RR d=gcd(k,m);
    	if(ind%d) return (void) puts("0");
    	R A=k/d,B=m/d; ind/=d; 
    	exgcd(A,B,x,y); (x*=ind)%=m; x=(x%B+B)%B;
    	cnt=0;
    	while(x<=m) ans[++cnt]=qpow(G,x),
    	x+=B; sort(ans+1,ans+cnt+1);
    	printf("%lld
    ",cnt); for(R i=1;i<=cnt;++i) printf("%lld ",ans[i]);
    }
    } signed main() {Luitaryi::main(); return 0;}
    

    2019.08.22
    78

  • 相关阅读:
    C# 导入Excel遇到数字字母混合列数据丢失解决
    C# 导出 Excel
    DataGridView 改变行列颜色
    EditPlus使用技巧
    jquery的事件与应用
    jquery操作DOM元素的复习
    jquery笔记
    jquery 和ajax
    jQuery笔记
    CSS相关知识三
  • 原文地址:https://www.cnblogs.com/Jackpei/p/11393645.html
Copyright © 2011-2022 走看看