首页 > 其他分享 >题解 P3306 [SDOI2013] 随机数生成器

题解 P3306 [SDOI2013] 随机数生成器

时间:2023-03-12 17:33:13浏览次数:49  
标签:return int 题解 生成器 rest pmod SDOI2013 equiv Mod

Link

它 \(p\) 都是质数了,这不就明示我们是 bsgs 了吗

我没看出来

然后我们来倒一下 \(n\) 天的式子

第一天是 \(x_1\),第二天是 \(ax_1+b\),第三天是 \(a^2x_1+(ab+b)\),第四天是 \(a^3x_1 +(a^2b+ab+b)\)。

我们一通大眼观察,观察出来第 \(n\) 天是 \(a^{n - 1}x_1+\sum\limits_{i = 0}^{n-2}a^ib\)。

然后由于我学艺不精赶紧滚回幼儿园重读!没有想到等比数列求和二年级小朋友 QAQ,我们拿等比数列求和公式往右边一套,就是 \(a^{n-1}x_1+\dfrac{(a^{n - 1} - 1)b}{a-1}\equiv t \pmod p\)

两边同时乘上 \(a - 1\),那么 \((a-1)a^{n - 1}x_1 + (a^{n - 1} - 1) b\equiv (a - 1)t\pmod p\)

我们不知道 \(n - 1\),\(n - 1\) 在指数位置上,我们考虑 BSGS,我们考虑把 \(a^{n-1}\) 给单独搞出来,左边化简得到 \((ax_1 - x_1+b)a^{n - 1} - b\equiv (a-1)t\pmod p\)

移项得到 \(a^{n - 1}\equiv \dfrac{(a-1)t + b}{ax_1 - x_1 + b} \pmod p\)。

好,BSGS 板子一套即可……吗?


全 T 了……离谱……

然后把数据一下,我们定睛一看,就会发现这样一个事情

有一些比较搞基的情况

  1. \(x_1 = 1\) 输出 \(1\) 即可。
  2. \(a = 0\)
    如果 \(t = b\),输出 \(2\)(第一天 \(x_1\),第二天 \(0 +b = b\)),否则输出 \(-1\)。
  3. \(a = 1\)。
    这个时候 \(x_n = x_1 + (n - 1)b\)。
    所以 \(x_1+(n-1)b\equiv t\pmod p\),战术移项一下 \((n - 1) \equiv (t - x_1)b^{-1}\pmod p\)

代码

一定要开 longlong!

//SIXIANG
#include <iostream>
#include <cmath>
#include <map>
#define MAXN 100000
#define int long long
#define QWQ cout << "QWQ" << endl;
using namespace std;
map <int, int> M;
int pp, a, b, x1, t;
int exgcd(int a, int b, int &x, int &y) {
	if(!b) {x = 1, y = 0; return a;}
	else {
		int rest = exgcd(b, a % b, x, y);
		int tmp = x; x = y, y = tmp - a / b * y;
		return rest;
	}
} 
int qmul(int n, int m, int Mod) {
	int rest = 0;
	while(m) {
		if(m & 1) rest = ((rest + n) % Mod + Mod) % Mod;
		m >>= 1, n = ((n + n) % Mod + Mod) % Mod;
	}
	return rest;
}
int qpow(int n, int m, int Mod) {
	int rest = 1;
	while(m) {
		if(m & 1) rest = qmul(rest, n, Mod) % Mod;
		m >>= 1, n = qmul(n, n, Mod) % Mod;
	}
	return rest;
}

void BSGS(int a, int b, int m) {
	int t = ceil(sqrt(m)), qwq = b % m, qaq = 1, quq = 1;
	M[qwq] = 0;
	for(int p = 1; p <= t; p++) {
		qwq = qwq * a % m;
		M[qwq] = p;
	}
	qaq = qpow(a, t, m);
	for(int p = 1; p <= t; p++) {
		quq = quq * qaq % m;
		if(M[quq]) {
			cout << ((p * t - M[quq]) % m + m) % m + 1 << endl;
			return ;
		}
	}
	cout << -1 << endl;
}
void get() {
	M.clear();
	if(t == x1) {
		cout << 1 << endl;
		return ;
	} 
	if(a == 0) {
		if(t == b) cout << 2 << endl;
		else cout << -1 << endl;
		return ;
	}
	if(a == 1) {
		if(!b) {
			cout << -1 << endl;
			return ;
		}
		int rt = (t - x1); 
		rt = (qmul(rt, (qpow(b, pp - 2, pp)), pp));
		cout << ((rt % pp) + pp) % pp + 1 << endl;
		return ;
	}
	
	int A = qmul(((a - 1) % pp + pp) % pp, t, pp);
	int B = qmul(a, x1, pp);
	int m = qmul((A + b), qpow(((B - x1 + b) % pp + pp) % pp, pp - 2, pp), pp);

	if((A + b) % pp == 0) cout << -1 << endl;
	else BSGS(a, m, pp);
}
void init() {
	cin >> pp >> a >> b >> x1 >> t;
	get();
}
signed main() {
	int T; cin >> T;
	while(T--)
		init();
}

标签:return,int,题解,生成器,rest,pmod,SDOI2013,equiv,Mod
From: https://www.cnblogs.com/thirty-two/p/17208514.html

相关文章

  • 【题解】CF1264D2
    题目大意给定一个长度为\(n\)的字符串,其中只有(,),?三种字符,其中?可以为(或者)对于一个括号序列,定义其权值为其通过删除字符后可以得到的合法的括号匹配的最深的深度,下......
  • AcWing 199. 余数之和 题解
    做了一下午……题解都看不懂,最后自己比比划划弄懂了。题意:给出\(n,k\),求\(\sum\limits_{i=1}^nk\modi\)。首先取模形式十分不好处理,所以我们可以根据取模运算定义做......
  • windows 文件夹打开默认是小窗口问题解决
    目录windows文件夹打开默认是小窗口问题解决问题解决windows文件夹打开默认是小窗口问题解决不知道误操作了什么,最近点击windows文件夹默认打开的都是小窗口,每次需要点......
  • 3 月 8 日测试题解
    3月8日测试题解T1题意给你一张图\(G=(V,E)\),\(|V|=n\),\(|E|=m\),带边权、点权。你可以执行以下操作任意多次:选取一个顶点,将其自身与与其相连的边删去当你......
  • 007 springboot集合mybatis-plus,使用其中的代码生成器
    代码生成器步骤一:在pom.xml中添加相应的依赖<!--代码生成器--><dependency><groupId>com.baomidou</groupId><artifactId>......
  • 2023.3.12 模拟赛题解
    天黑黑题意大致:给出含\(\max\)和\(+\)的表达式以及其中的\(n\)个数,求其最大值。用前缀表达式的形式给出,X表示一个要填的数,B表示\(\max\),A表示\(+\)。题解......
  • CF915E 题解(动态开点线段树)
    题目传送门简要题意:题面就挺简要的。看到题目第一眼想到线段树,再看一眼数据范围,\(1≤n≤10^9\),寄,既然不能直接用线段树,那怎么办呢?可以离散化,为了避免麻烦的离散化,......
  • P2782 友好城市题解
    题目传送门题意:给定一些上下的线段,求出最多不相交的线段数量。一开始看错题了,以为是给定一堆线段,求出线段最大不交数量,然后就写了一个树状数组优化\(dp\)结果样例都不过,......
  • CF1785D Range = √Sum 题解
    题目传送门(第一次CF场切绿欸)题意考虑将这段序列的平均数设为\(4n\),那么总和就会是\(4n^2\),这时候就需要让最值差等于\(2n\),直接让他等于\(3n\)和\(5n\)就可......
  • 【题解】CF1801G A task for substrings
    考虑拆开贡献,前缀贡献痕容易算。而跨越\([l-1,l]\)的贡献,考虑在正串ACAM找到\([1,l-1]\),反串ACAM找到\([l,r]\),那么要做的就是在两串的fail链祖先上,找到能凑成完......