zoukankan      html  css  js  c++  java
  • 【文文殿下】【SDOI2013】随机数生成器 题解

    题意

    给你个随机数生成器 (f(x) = a*f(x-1)+b (mod p)),给你初始信息(a,b,t,p,f(1)),问你几次等于(t),如果不等于输出(-1).

    题解

    [f(n) = a*f(n-1)+b ]

    [f(n) = c*a^{n-1} + frac {b(a^n-1)}{a-1} ext { where c is an arbitrary parameter} ]

    不过上面这个式子咱推不出来,考虑矩阵乘法

    [egin{pmatrix} a&b\ 0&1 end{pmatrix}^x imes egin{pmatrix} f(1)\ 1 end {pmatrix} = egin{pmatrix} t\ 1 end{pmatrix}]

    我们考虑一个BSGS用到矩阵上,就把他做了。
    如果你要用这个式子的话

    [a^{isqrt{p} + k} = b (mod p) ]

    前面那个转移矩阵的逆矩阵是

    [egin{pmatrix} frac{1}{a}&-frac{b}{a}\ 0&1 end{pmatrix} ]

    但我懒得用用逆矩阵,直接用下面的这个式子。

    [a^{isqrt{p} - k} = b (mod p) ]

    带了矩阵常数贼大,我还懒得手写hashtable,吸着氧过了。
    估计思路这么清(zhi)奇(zhang)的人没几个吧。

    #include<bits/stdc++.h>
    using namespace std;
    int p;
    int inc(int a,int b) {
    	a+=b;
    	return a>=p?a-p:a;
    }
    int dec(int a,int b) {
    	a-=b;
    	return a<0?a+p:a;
    }
    int mul(int a,int b) {
    	return 1LL*a*b%p;
    }
    struct qwq {
    	int r,c;
    	int a[3][3];
    	qwq(){
    		memset(a,0,sizeof a);
    		r=c=0;
    	}
    	qwq operator * (const qwq& rhs) const {
    		qwq ret;
    		ret.r = r,ret.c = rhs.c;
    		for(int i=1;i<=r;++i) {
    			for(int j=1;j<=rhs.c;++j) {
    				for(int k=1;k<=c;++k) {
    					ret.a[i][j]=inc(ret.a[i][j],mul(a[i][k],rhs.a[k][j]));
    				}
    			}
    		}
    		return ret;
    	}
    	bool operator < (const qwq& rhs) const {
    		if(r!=rhs.r) return r<rhs.r;
    		if(c!=rhs.c) return c<rhs.c;
    		for(int i=1;i<=r;++i)
    			for(int j=1;j<=c;++j)
    				if(a[i][j]!=rhs.a[i][j])
    					return a[i][j]<rhs.a[i][j];
    		return 0;
    	}
    };
    int T,a,b,x1,t,ans;
    qwq qpow(qwq a,int b) {
    	assert(b>=0);
    	qwq ret;
    	ret.r=a.r,ret.c=a.c;
    	for(int i=1;i<=ret.r;++i) ret.a[i][i]=1;
    	while(b) {
    		if(b&1) ret=ret*a;
    		a = a * a;
    		b>>=1;
    	}
    	return ret;
    }
    bool BSGS(void) {
    	map<qwq,int> M;
    	M.clear();
    	int lmt = sqrt(p)+1;
    	ans = 0x3f3f3f3f;
    	qwq base;
    	base.a[1][1]=a,base.a[1][2]=b,base.a[2][2]=1;
    	base.r=base.c=2;
    	qwq fn;
    	fn.r=2,fn.c=1;
    	fn.a[1][1]=t,fn.a[2][1]=1;
    	qwq st;
    	st.r=2,st.c=1;
    	st.a[1][1]=x1,st.a[2][1]=1;
    	qwq step = qpow(base,lmt);
    	for(int i=1;i<=lmt+1;++i) {
    		st = step*st;
    		if(!M.count(st)) {
    			M[st]=i;
    		}
    	}
    	bool flag = 0;
    	for(int i=0;i<=lmt;++i) {
    		if(i) fn = base*fn;
    		if(M.count(fn)) {
    			flag = 1;
    			ans = min(ans,M[fn]*lmt-i);
    		}
    	}
    	return flag;
    }
    int main() {
    	scanf("%d",&T);
    	while(T--) {
    		scanf("%d%d%d%d%d",&p,&a,&b,&x1,&t);
    		if(a==0) {
    			if(x1==t)
    				puts("1");
    			else {
    				if(b==t) {
    					puts("2");
    				}
    				else {
    					puts("-1");
    				}
    			}
    		}
    		else {
    			if(BSGS()) {
    				printf("%d
    ",ans+1);
    			}
    			else {
    				puts("-1");
    			}
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    5、Android Service测试
    javassist示例
    HeaderExchangeClient
    dubbo 心跳
    javassist和jdk动态代理
    dubbo为consumer创建代理
    线程同步知识点
    SynchronousQueue类
    Executors类的newFixedThreadPool, newCachedThreadPool, newScheduledThreadPool
    eclipse设置条件断点
  • 原文地址:https://www.cnblogs.com/Syameimaru/p/11066837.html
Copyright © 2011-2022 走看看