• BZOJ 3122 【SDOI2013】 随机数生成器


    题目链接:随机数生成器

      经典数学题……

      为了方便接下来的处理,我们可以先把(X_1=t)的情况特判掉。

      当(a=0)的时候显然只需再判一下(b)是否等于(t)即可。

      当(a=1)的时候就变成了一次的同余方程,直接用拓展欧几里得解出来即可。

      当(a>1)的时候可以等比数列求和,对于(i>1),得到(X_i=a^{i-1}X_1+frac{a^{i-1}-1}{a-1}b)。

      由于(p)是质数,那么(a-1)就有逆元。于是移下项,最后剩下一个形如(a^{i-1}equiv y pmod p)的方程,大步小步解出来即可。

      下面贴代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    #define mod 2000029
    
    using namespace std;
    typedef long long llg;
    
    int T,a,b,x1,t,p;
    struct hash{
    	int head[mod],next[mod],c[mod],tt,d[mod],ld;
    	int to[mod]; bool vis[mod];
    	int find(int now){
    		int u=now%mod;
    		for(int i=head[u];i;i=next[i])
    			if(to[i]==now) return i;
    		return 0;
    	}
    	void insert(int now,int i){
    		int u=now%mod,v;
    		if((v=find(now))){c[v]=i;return;}
    		if(!vis[u]) vis[u]=1,d[++ld]=u; c[++tt]=i;
    		to[tt]=now; next[tt]=head[u]; head[u]=tt;
    	}
    	void finalize(){
    		for(int i=1;i<=ld;i++) vis[d[i]]=0,head[d[i]]=0;
    		ld=0; tt=0;
    	}
    }A;
    
    int gcd(int x,int y){
    	int r=x%y;
    	while(r) x=y,y=r,r=x%y;
    	return y;
    }
    
    int exgcd(int a,int b,int &x,int &y){
    	if(!b){x=1;y=0;return a;}
    	int aa=exgcd(b,a%b,x,y),bb=x;
    	x=y; y=bb-1ll*(a/b)*y%p; if(y<0) y+=p;
    	return aa;
    }
    
    int mi(int a,int b){
    	int s=1;
    	while(b){
    		if(b&1) s=1ll*s*a%p;
    		a=1ll*a*a%p; b>>=1;
    	}
    	return s;
    }
    
    int main(){
    	File("a");
    	scanf("%d",&T);
    	while(T--){
    		scanf("%d %d %d %d %d",&p,&a,&b,&x1,&t);
    		if(x1==t){printf("1
    ");continue;}
    		if(a==0) printf(b==t?"2
    ":"-1
    ");
    		else if(a==1){
    			int X=t-x1,x,y,q;
    			if(X<0) X+=p; q=exgcd(b,p,x,y);
    			if(X%q) printf("-1
    ");
    			else{
    				x=1ll*x*(X/q)%p; x%=1ll*(p/q)*(b/q);
    				printf("%d
    ",x+1);
    			}
    		}
    		else{
    			b=1ll*b*mi(a-1,p-2)%p; t+=b;
    			t=1ll*t*mi(x1+b,p-2)%p;
    			int N=sqrt(p)+1,y=mi(a,N),ans=p+1;
    			for(int i=0,x=t;i<N;i++) A.insert(x,i),x=1ll*x*a%p;
    			for(int i=1,j=N,x=y,u;j<=p+N;j+=N,i++,x=1ll*x*y%p)
    				if((u=A.find(x))) ans=min(ans,i*N-A.c[u]);
    			if(ans==p+1) printf("-1
    ");
    			else printf("%d
    ",ans+1);
    			A.finalize();
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    git 一般的使用操作
    php 导出excel,csv
    安装sublime_text_3
    安装mongodb记录,mongo基本命令记录
    redis 安装记录
    YII2 activeform样式修改
    go 安装下载
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.hbsjz/com.hbsjz.BaseMapActivity}:
    SQLServer创建触发器,更新表
    SQL Server触发器创建、删除、修改、查看示例步骤
  • 原文地址:https://www.cnblogs.com/lcf-2000/p/6404155.html
Copyright © 2020-2023  润新知