• P3306 [SDOI2013] 随机数生成器


    题目描述:

    洛谷

    最近小 W 准备读一本新书,这本书一共有 (p) 页,页码范围为 (0 sim p-1)

    小 W 很忙,所以每天只能读一页书。为了使事情有趣一些,他打算使用 NOI2012 上学习的线性同余法生成一个序列,来决定每天具体读哪一页。

    我们用 (x_i) 来表示通过这种方法生成出来的第 (i) 个数,也即小 W 第 (i) 天会读哪一页。这个方法需要设置 (3) 个参数 (a,b,x_1),满足 (0leq a,b,x_1lt p),且 (a,b,x_1) 都是整数。按照下面的公式生成出来一系列的整数:

    $x_{i+1} equiv a imes x_i+b pmod p $

    其中 ( mod) 表示取余操作。

    但是这种方法可能导致某两天读的页码一样。

    小 W 要读这本书的第 (t) 页,所以他想知道最早在哪一天能读到第 (t) 页,或者指出他永远不会读到第 (t) 页。

    数据范围:(1leq Tleq 50), (0 leq a, b, x_1, t lt p), (2 leq p leq 10^9), (p) 为质数。

    solution

    我们尝试打一下表,找找规律:

    (x_2 = ax_1 + b)

    (x_3 = a^2x_1 + ab + b)

    (x_4 = a^3x_1 + a^2b + ab + b)

    (x_5 = a^4x_1 + a^3b + a^2b + ab + b)

    (x_6 = a^5x_1 + a^4b + a^3b + a^2b + ab + b)

    不难发现: (x_n = a^{n-1}x_1 + displaystylesum_{i=0}^{n-2} a^ib, (x gt 1))

    根据等比数列的求和公式则有: (displaystylesum_{i=0}^{n-2} a^ib = b{1-a^{n-1}over 1-a})

    带入可得:(x_n = a^{n-1}x_1 + {bover 1-a} (1-a^{n-1}))

    化简一下:

    (x_n = a^{n-1}x_1 + {bover 1-a} (1-a^{n-1}))

    (x_n = a^{n-1}x_1 - a^{n-1}{bover 1-a} + {bover 1-a})

    (B = {bover 1-a}), 则原式可以化为:

    (x_n = (x_1-B) a^{n-1} + B)

    (ecause x_n equiv t)

    ( herefore (x_1-B) a^{n-1} + Bequiv t)

    ( herefore (x_1-B)a^{n-1} equiv t-B pmod p)

    ( herefore a^{n-1} equiv {t-Bover x_1-B} pmod p)

    (BSGS) 算法求解即可。

    几个需要特判的点 (被卡到吐):

    • (x_1 = t) 的时候,直接输出 (1)
    • (a = 0) 的时候,如果 (t = b) 输出 (1) , 反之输出 (-1)
    • (a = 1) 的时候, 如果 (b = 0)(x eq t) 输出 (-1), 否则输出 ((t-x) over b)

    Code

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<map>
    #include<cmath>
    using namespace std;
    #define int long long
    int T,a,b,p,x,t;
    inline int read()
    {
        int s = 0, w = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
        while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0'; ch = getchar();}
        return s * w;
    }
    int ksm(int a,int b)
    {
    	int res = 1;
    	for(; b; b >>= 1)
    	{
    		if(b & 1) res = res * a % p;
    		a = a * a % p; 
    	}
    	return res;
    }
    int BSGS(int a,int b,int p)
    {
    	map<int,int> hash;
    	int m = sqrt(p) + 1;
    	for(int i = 0; i <= m; i++)
    	{
    		int val = b * ksm(a,i) % p;
    		hash[val] = i;
    	}
    	a = ksm(a,m);
    	for(int i = 0; i <= m; i++)
    	{
    		int val = ksm(a,i);
    		int j = hash.find(val) == hash.end() ? -1 : hash[val];
    		if(j > 0 && i * m - j > 0) return i * m - j;
    	}
    	return -1;
    }
    signed main()
    {
    	T = read();
    	while(T--)
    	{
    		p = read(); a = read(); b = read(); x = read(); t = read();
    		if(x == t){printf("%d
    ",1); continue;}
    		if(a == 0)
    		{
    			if(t == x) printf("%d
    ",1);
    			else if(t == b) printf("%d
    ",2);
    			else printf("%d
    ",-1);
    			continue; 
    		}
    		if(a == 1)
    		{
    			if(b == 0 && x != t) printf("%d
    ",-1);
    			else printf("%lld
    ",(((t-x+p)%p)*ksm(b,p-2)%p)+1);
    			continue;
    		}
    		int tmp = (1 - a + p) % p;
    		int inv = ksm(tmp,p-2);
    		t = (t - (b * inv % p) + p) % p;
    		x = (x - (b * inv % p) + p) % p;
    		t = t * ksm(x,p-2) % p;
    		int ans = BSGS(a,t,p);
    		if(ans == -1) printf("%d
    ",-1);
    		else printf("%lld
    ",ans+1); 
    	}
    	return 0;
    
    
  • 相关阅读:
    最新美丽说网购平台模板
    红色的原油投资金融专题模板
    简单响应式Bootstrap框架中文官网页面模板
    蓝色简约的工业大学学校网站静态模板
    红色经典招生校园网站全套
    白色简洁的瑞班克个人博客网站
    仿360影视网站模板html
    红色的企业新闻门户网站模板
    橙色的汽车蚂蚁企业门户网站模板
    使用ExtJS做一个用户的增删改查
  • 原文地址:https://www.cnblogs.com/genshy/p/14454939.html
Copyright © 2020-2023  润新知