首页 > 其他分享 >230526 // 小数论复习

230526 // 小数论复习

时间:2023-05-27 18:55:18浏览次数:33  
标签:return 复习 数论 230526 times int k1 read inline

裁决已至!

称量,你的罪恶!

以此身,肃正万象!

人总是越活越抽象的,所以怎么还不考期末,我要考期末!


A. Min

http://222.180.160.110:1024/contest/3641/problem/1

给出 \(n\) 个数 \(A_{1\sim n}\),现求一组整数序列 \(X_{1\sim n}\) 使得 \(S = A_1 \times X_1 + A_2 \times X_2 + \cdots + A_n \times X_n > 0\),且 \(S\) 的值最小。求 \(S_{\min}\)。

题目给得莫名奇妙。不过我们既然要让其尽可能接近 \(0\),而又不等于 \(0\),怎么做呢?

先将数组中所有元素取绝对值。对于两个互质的正数 \(a, b\),能否找到一组 \((x, y)\),满足 \(ax + by = 1\) 呢?

这是什么?裴蜀定理!所以一定能找到一组整数解 \((x, y)\),满足上述不定方程。

对于任意两个数 \(a_1, b_1\),假设其最大公约数为 \(g\),那我们一定能找到一组 \((x_1, y_1)\),满足 \(\dfrac {a_1} {g} \times x_1 + \dfrac {b_1} {g} \times y_1 = 1\)。相应地,一定有 \(a_1 x_1 + b_1 y_1 = g\)。并且 \(\text{RSH}\) 的最小正数值就是 \(g\),因为 \(a_1, b_1\) 不可能通过任意加乘操作(即初等行变换操作)得到一个不包含因子 \(g\) 的值。

故对于给定的数组,求解其所有元素绝对值的 \(\gcd\) 即可。

using namespace fastIO;
int n, g, x;
inline int abs(int x) {
	return x >= 0 ? x : -x;
}
int gcd(int x, int y) {
	return y ? gcd(y, x % y) : x;
}
int main() {
	read(n);
	while (n--) {
		read(x);
		g = gcd(g, abs(x));
	}
	print(g);
	return 0;
}
} // namespace XSC062

B. 向量

http://222.180.160.110:1024/contest/3641/problem/2

给定一对数 \((a, b)\),你可以任意使用 \((a, b), (a,-b), (-a,b), (-a,-b), (b,a), (b,-a), (-b,a), (-b,-a)\) 这些数对,使得它们之和为 \((x, y)\)。

我记得我写过题解来着…… 找到了。

首先,我们不将 \(x, y\) 合并处理,各凑各的。

可以得到:

\[n_1 \times a + m_1 \times b = x \\ n_2 \times a + m_2 \times b = y \]

而以上两式 分别 是否有解,可以用裴蜀定理方便地判断,即 \((a,b)\mid x\) 和 \((a,b)\mid y\) 是否成立。

可是分别有解并不代表能同时有解。为了探究两式是否能同时有解,我们先直接将两式相加。

\[(n_1 + n_2) \times a + (m_1 + m_2) \times b = x + y \]

但这个式子是否有解仅等价于上两式是否同时有解,并不一定在题面的应用场景中成立(即未对系数加以限制,导致不一定存在一组满足题意的解),与我们的目的不符。

不难发现,题目中的向量可以分为两种:\(a, b\) 同号、\(a, b\) 异号。

于是我们将 \(\text {LSH}\) 替换为同号、异号的向量相加的结果,得到:

\[n_3 \times (a + b) + m_3 \times (a - b) = x + y \]

裴蜀定理判断该式和最开头的两个式子是否有解即可。

注意到 \(x + y\) 的操作,实际上是需要开 long long 的。

#define int long long
namespace XSC062 {
using namespace fastIO;
int T, a, b, x, y, g1, g2;
int gcd(int x, int y) {
	return y ? gcd(y, x % y) : x;
}
int main() {
	read(T);
	while (T--) {
		read(a), read(b);
		read(x), read(y);
		g1 = gcd(a, b);
		g2 = gcd(a + b, a - b);
		if (((x + y) % g2 == 0) &&
			(x % g1 == 0) && (y % g1 == 0))
			puts("Y");
		else puts("N");
	}
	return 0;
}
} // namespace XSC062
#undef int

C. 青蛙的约会

http://222.180.160.110:1024/contest/3641/problem/3

两只青蛙在长度为 \(L\) 的环形数轴上往前跳,一只从 \(x\) 开始,一次跳 \(m\) 步;另一只从 \(y\) 开始,一次跳 \(n\) 步。每一次两只青蛙都会同时往前跳一步,求它们跳了几次才能碰头。

省流:\(x + m \times a \equiv y + n \times a \pmod L\)。设成负数是为了好操作。

那么有 \(x + m \times a - y - n \times a = b \times L\)。

化简为 \((m - n) \times a - L \times b = y - x\)。

exgcd 即可。

#define int long long
namespace XSC062 {
using namespace fastIO;
int x, y, m, n, L, k1, k2, g;
inline void swap(int &x, int &y) {
	x ^= y ^= x ^= y;
	return;
}
inline int exgcd(int x, int y) {
	if (y == 0) {
		k1 = 1, k2 = 0;
		return x;
	}
	int u = exgcd(y, x % y), t = k1;
	k1 = k2, k2 = t - (x / y) * k2;
	return u;
}
int main() {
	read(x), read(y);
	read(m), read(n), read(L);
	if (m - n < 0)
		swap(m, n), swap(x, y);
	g = exgcd(m - n, L);
	if ((y - x) % g) {
		puts("Impossible");
		return 0;
	}
	k1 *= (y - x) / g, L /= g;
	k1 = ((k1 % L) + L) % L;
	print(k1);
	return 0;
}
} // namespace XSC062
#undef int

D. 荒岛野人

http://222.180.160.110:1024/contest/3641/problem/4

有 \(N\) 个野人住在长度为 \(M\) 的环形数轴上,每个以 \(C_i\) 为起点,往前走 \(P_i\) 步,能活 \(L_i\) 年,问 \(M\) 至少要多大,才能保证在所有野人死掉前没有两个人撞到一起。保证 \(M\) 有解且 \(M \le 10^6\)。

这个 \(M\) 的范围限制给的,就差把「枚举 \(M\) 并 \(\mathcal O(N^2)\) 验证正确性」写出来了。

那么问题就在于如何验证正确性。很简单,我们对于任意两个野人 \(i, j\),exgcd 一下,看看相撞的日期是否短于两方的寿命即可。判定方式和青蛙那道题类似,所以我直接复制粘贴了

#define int long long
namespace XSC062 {
using namespace fastIO;
const int maxn = 25;
const int inf = 1e18;
int n, mx;
int c[maxn], p[maxn], l[maxn];
inline int min(int x, int y) {
	return x < y ? x : y;
}
inline int max(int x, int y) {
	return x > y ? x : y;
}
inline void swap(int &x, int &y) {
	x ^= y ^= x ^= y;
	return;
}
inline int exgcd(int x, int y,
					int &k1, int &k2) {
	if (y == 0) {
		k1 = 1, k2 = 0;
		return x;
	}
	int u = exgcd(y, x % y, k1, k2);
	int t = k1;
	k1 = k2, k2 = t - (x / y) * k2;
	return u;
}
inline int calc(int m, int n,
					int x, int y, int L) {
	if (m - n < 0)
		swap(m, n), swap(x, y);
	int k1, k2;
	int g = exgcd(m - n, L, k1, k2);
	if ((y - x) % g)
		return inf;
	k1 *= (y - x) / g, L /= g;
	k1 = ((k1 % L) + L) % L;
	return k1;
}
inline bool check(int m) {
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j < i; ++j) {
			if (calc(p[i], p[j], c[i],
				c[j], m) <= min(l[i], l[j]))
				return 0;
		}
	}
	return 1;
}
int main() {
	read(n);
	for (int i = 1; i <= n; ++i) {
		read(c[i]), read(p[i]);
		read(l[i]), mx = max(mx, c[i]);
	}
	for (int i = mx; ; ++i) {
		if (check(i)) {
			print(i);
			break;
		}
	}
	return 0;
}
} // namespace XSC062
#undef int

E. Sumdiv

http://222.180.160.110:1024/contest/3641/problem/5

求 \(A^B\) 的所有约数之和 \(\bmod 9901\)。

假设 \(A = p_1 ^ {d_1} \times p_2 ^ {d_2} \times \cdots \times p_N ^ {d_N}\),那么有 \(A^B = p_1 ^ {d_1\times B} \times p_2 ^ {d_2\times B} \times \cdots \times p_N ^ {d_N\times B}\)。

那么可以得到答案值为 \(\prod_{i=1}^N (p_i ^ {d_i \times B + 1} - 1) \div (p_i - 1)\)。后面的内容就是对于 \(p_i\) 的所有因数和。

怎么得到的呢?明显 \(p_i\) 的因数和其实就是幂次和,即 \(\sum_{j = 1}^{d_i\times B}{p_i}^j\)。这是什么?等比数列!整一个求和公式就可以了。

取模的话好处理,随便逆元一下就可以了。

#define int long long
namespace XSC062 {
using namespace fastIO;
const int mod = 9901;
int A, B, res = 1;
inline int qkp(int x, int y) {
	int res = 1;
	while (y) {
		if (y & 1)
			(res *= x) %= mod;
		(x *= x) %= mod;
		y >>= 1;
	}
	return res;
}
inline int getinv(int x) {
	return qkp(x, mod - 2);
}
inline int calc(int p, int d) {
	return ((qkp(p, d + 1) - 1) *
					getinv(p - 1)) % mod;
}
int main() {
	read(A), read(B);
	for (int i = 2; i <= A; ++i) {
		if (A % i)
			continue;
		int tot = 0;
		while (A % i == 0)
			++tot, A /= i;
		(res *= calc(i, tot * B)) %= mod;
	}
	print(res);
	return 0;
}
} // namespace XSC062
#undef int

F. 排课表

http://222.180.160.110:1024/contest/3641/problem/6

在 \(n\) 节课中选 \(m\) 节来上,\(n\) 节课中有 \(a\) 节不能放在第一节,\(b\) 节不能放在最后一节,两者无重合,求排课方案数。

小容一个斥。算出总方案数,减去第一节课选了 \(a\) 节中某一节的方案数,再减去最后一节课选了 \(b\) 节中的某一节的方案数,最后加上第一节选了 \(a\) 节中的某一节、同时最后一节课选了 \(b\) 节中的某一节的方案数即可。

那么答案的值就是 \(A_n^m - a * A_{n - 1} ^ {m - 1} - b * A_{n - 1} ^ {m - 1} + a * b * A(n - 2, m - 2)\)。

#define int long long
namespace XSC062 {
using namespace fastIO;
const int lim = 1e5;
const int maxn = 1e5 + 5;
const int mod = 998244353;
int fac[maxn];
int T, n, m, a, b, res;
inline int qkp(int x, int y) {
	int res = 1;
	while (y) {
		if (y & 1)
			(res *= x) %= mod;
		(x *= x) %= mod;
		y >>= 1;
	}
	return res;
}
inline int getinv(int x) {
	return qkp(x, mod - 2);
}
inline int A(int n, int m) {
	return (fac[n] * getinv(fac[n - m])) % mod;
}
int main() {
#ifdef ONLINE_JUDGE
	freopen("arrange.in", "r", stdin);
	freopen("arrange.out", "w", stdout);
#endif
	read(T);
	fac[0] = 1;
	for (int i = 1; i <= lim; ++i)
		fac[i] = (fac[i - 1] * i) % mod;
	while (T--) {
		read(n), read(m);
		read(a), read(b);
		res = A(n, m) - a * A(n - 1, m - 1);
		res = (res % mod + mod) % mod;
		res -= A(n - 1, m - 1) * b;
		res = (res % mod + mod) % mod;
		res += a * A(n - 2, m - 2) * b;
		res %= mod;
		print(res, '\n');
	}
	return 0;
}
} // namespace XSC062
#undef int

标签:return,复习,数论,230526,times,int,k1,read,inline
From: https://www.cnblogs.com/XSC062/p/17435598.html

相关文章

  • 关于一些初等数论的证明
    未完工。目前咕掉的:卢卡斯定理真正有用的一个没有质数:威尔逊定理:\(p\)为质数的充要条件为\((p-1)!\equiv-1\pmodp\)证明:\(1.\)充分性:反证,假设\(p\)是合数。如果\(p\)为质数的平方,例如\(p=4\),则\(3!\equiv2\pmod4\),不成立。令\(p=k^2\),因为\(p>4\),所以\(......
  • 初等数论(Ⅲ):高次同余、阶和原根相关
    前言关于高次同余方程,有\(a^x\equivb(\text{mod}\p)\)和\(x^a\equivb(\text{mod}\p)\)两种类型,后者计算起来较为麻烦,下文就分别记述这两种高次同余方程。离散对数问题离散对数问题是在模\(p\)意义下求解\(\log_ab\),这等价于形如\[a^x\equivb(\text{mod}\p)......
  • 软构复习5
    可维护性的常见度量指标可维护性:易于修改软件系统和组件来更正可扩展性灵活性可适应性:交互式系统(自适应系统)的能力,它可以根据所获得的关于用户及其环境的信息来适应个人用户的行为可管理性支持性高内聚,低耦合:要尽量避免其与其他类型的许多相互依赖而难以复用和维护的设计......
  • 复习JavaDay07
    线程的5种状态新生状态:Threadthread=newThread();就绪状态:当调用start()方法,线程立即进入就绪状态,但并不以为着立即调度执行运行状态:进入运行状态,线程才真正执行线程体的代码块。阻塞状态:当调用sleep(),wait或者同步锁时,线程进入阻塞状态,就是代码不往下执行阻塞事件解......
  • 关于软件构造第二部分(PPT4-8)的总结复习
    一、基本数据类型、对象数据类型基本数据类型:int、long、boolean、double等,——有值,无ID,无法区分,不可变,在栈中分配内存,代价低;对象数据类型:String、Date等——有值,有ID,可为可变也可为不可变,在堆中分配内存,代价昂贵;可将基本数据类型包装为动态数据类型(首字母变大写)通常在定义集合......
  • 数据结构期末复习——图的遍历
    图的遍历:1.定义:从某个结点出发访问遍图中结点,且使每个结点仅被访问一次图的遍历具有复杂性,主要体现在以下几点1.遍历没有规定从哪个结点开始访问,因此从任意结点开始访问均可2.图的一个结点可以连接多个结点,因此无法确定访问此结点之后应该访问哪一个结点3.如果一个图中存在回......
  • 移动互联APP复习题
    一.判断题1.Android是一种操作系统但不是一种开发平台。(F)2.Intent是用于传递参数和页面的切换的组件。(T)3.Android的更新需要在主线程上执行。(T)4.无论Service是以启动方式还是绑定方式运行都要重写onBind方法(T)5.后台服务是运行在另外一个线程上的也就是所谓的子线程。(F......
  • C语言复习题
    写在前面:大家好,我是花狗Fdog,来自内蒙古的一个小城市,目前在泰州读书。很感谢能有这样一个平台让我能够在这里分享所学所感。我喜欢编程,喜欢代码,喜欢去做一个程序员。努力学习,争取多年后,给亲人更好的生活。文章目录一、选择题二、填空题三、编程题一、选择题1.源程序TEST.C经......
  • 我的软考复习笔记【中级软件设计师】
    目录内聚与耦合内聚耦合统一过程(UP)软件体系结构风格软件能力成熟度模型(CMM)集成测试策略软件测试方法黑盒测试白盒测试需求UML分类协作图的边界类控制类实体类怎么区别null用例图的关系泛化(Inheritance)扩展(extend):包含(include):快速辨认类图的符号1.关联2.泛化3.聚合组件图设......
  • 动态内存分配复习
    动态内存分配复习为什么要使用动态内存分配:在声明数组时,必须用一个编译常量指定数组长度,但是,数组的长度往往只有在运行的时候才能被确定,这是因为它所需要的内存空间取决于输入数据,但是容易浪费空间,又或者容易溢出malloc和free:malloc执行动态内存分配,free执行释放内存,当使用mal......