zoukankan      html  css  js  c++  java
  • 【洛谷P3306】随机数生成器

    题目

    题目链接:https://www.luogu.com.cn/problem/P3306
    小W喜欢读书,尤其喜欢读《约翰克里斯朵夫》。最近小W准备读一本新书,这本书一共有\(P\)页,页码范围为\(0 \cdots P-1\)
    小W很忙,所以每天只能读一页书。为了使事情有趣一些,他打算使用NOI2012上学习的线性同余法生成一个序列,来决定每天具体读哪一页。
    我们用Xi来表示通过这种方法生成出来的第\(i\)个数,也即小\(W\)\(i\)天会读哪一页。这个方法需要设置\(3\)个参数\(a,b,X1\),满足\(0\leq a,b,X1\leq p-1\),且\(a,b,X1\)都是整数。按照下面的公式生成出来一系列的整数:\(X_{i+1} \equiv aX_i+b \pmod p\)其中\(mod\)表示取余操作。
    但是这种方法可能导致某两天读的页码一样。
    小W要读这本书的第\(t\)页,所以他想知道最早在哪一天能读到第t页,或者指出他永远不会读到第\(t\)页。

    思路

    题目意思就是给你一个递推式\(X_i=aX_{i-1}+b\)\(X_1\),让你求一个最小的\(i\)使得\(X_i\equiv t \pmod p\)
    大力推柿子,容易得到

    \[X_i=a^{i-1}X_1+a^{i-2}b+a^{i-3}b+...+b \]

    我们发现所有含有\(b\)的项是一个等比数列,所以可以用等比数列求和公式化简。

    \[X_i=a^{i-1}X_1+\frac{a^{i-1}b-b}{a-1} \]

    也就是要求

    \[t\equiv a^{i-1}X_1+\frac{a^{i-1}b-b}{a-1} \pmod p \]

    在这个柿子中,只有\(a^{i-1}\)是未知的。所以考虑化简出\(a^{i-1}\)

    \[t+\frac{b}{a-1}\equiv a^{i-1}X_1+\frac{a^{i-1}b}{a-1} \pmod p \]

    \[t+\frac{b}{a-1}\equiv a^{i-1}(X_1+\frac{b}{a-1}) \pmod p \]

    所以

    \[a^{i-1}\equiv \frac{t+\frac{b}{a-1}}{X_1+\frac{b}{a-1}}\pmod p \]

    \[a^{i-1}\equiv \frac{ta-t+b}{X_1a-X_1+b}\pmod p \]

    \(BSGS\)求出\(i-1\)即可。

    需要特判以下几点:

    1. \(X_1=t\)时,答案就是1。
    2. \(a=0\)时,第一天已经在\((1)\)中特判了,从第二天起,页码都是\(b\)。所以如果\(b=t\)答案即为2,否则无解。
    3. \(a=1\)
    • 如果\(b=0\),那么每天页码都是\(X_1\),所以若\(X_1≠t\)则无解
    • 如果\(b>0\),那么有\(X_1+xb\equiv t \pmod p\),即\(x\equiv \frac{t-X_1}{b}\pmod p\),用费马小定理即可求出\(x\)

    代码

    #include <map>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    
    ll p,a,b,x1,t;
    int T;
    map<int,int> hash;
    
    ll power(ll x,ll k,ll MOD)
    {
    	ll ans=1;
    	x%=MOD;
    	for (;k;k>>=1,x=x*x%MOD)
    		if (k&1) ans=ans*x%MOD;
    	return ans;
    }
    
    ll BSGS()
    {
    	hash.clear();
    	t=ceil(sqrt(p));
    	for (int i=0;i<=t;i++)
    		hash[b*power(a,i,p)%p]=i;
    	a=power(a,t,p);
    	for (int i=1;i<=t;i++)
    	{
    		ll val=power(a,i,p);
    		if (hash[val]) return ((i*t-hash[val])%p+p)%p;
    	}
    	return -2;
    }
    
    int main()
    {
    	scanf("%d",&T);
    	while (T--)
    	{
    		scanf("%lld%lld%lld%lld%lld",&p,&a,&b,&x1,&t);
    		if (x1==t) printf("1\n");
    		else if (!a)
    		{
    			if (b==t) printf("2\n");
    				else printf("-1\n");
    		}
    		else if (a==1)
    		{
    			if (!b) printf("-1\n");
    				else printf("%lld\n",((t-x1)%p+p)%p*power(b,p-2,p)%p+1);
    		}
    		else
    		{
    			b=(t*a-t+b)%p*power(x1*a-x1+b,p-2,p)%p;
    			printf("%lld\n",BSGS()+1);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    HDU 1116 Play on Words(并查集和欧拉回路)(有向图的欧拉回路)
    PHP 错误与异常 笔记与总结(8)自定义错误处理函数 set_error_handler()
    【VR】Leap Motion 官网文档 FingerModel (手指模型)
    2014年辛星解读Javascript之DOM之事件及其绑定
    java.util.logging.Logger使用具体解释
    技术走向管理一些思考(8)-适合的人才
    rac_grid自检提示缺少cvuqdisk包
    C++第15周(春)项目3
    交换a、b的值temp = a; a = b; b = temp;比a = a^b;b = a^b;a = a^b;快
    BZOJ 1089 SCOI2003 严格n元树 动态规划+高精度
  • 原文地址:https://www.cnblogs.com/stoorz/p/12236384.html
Copyright © 2011-2022 走看看