信息学奥赛一本通 1640:C Looooops

【题目链接】

ybt 1640:C Looooops
LOJ 10218. 「一本通 6.4 练习 4」C Looooops

【题目考点】

1. 线性同余方程

相关知识见 【模板】洛谷 P1082 NOIP 2012 提高组 同余方程

【解题思路】

在C或C++的 k k k位存储系统,可以存储 0 , 2 k − 1 0, 2\^k-1 0,2k−1范围内的整数。如unsigned int类型的范围为 0 , 2 32 − 1 0, 2\^{32}-1 0,232−1,unsigned long long类型的范围为 0 , 2 64 − 1 0, 2\^{64}-1 0,264−1

当变量的数值超出了该数据类型可以表示的范围,会发生"自然溢出",变量在二进制下只会保留末 k k k位,在数值角度看相当于进行了   m o d   2 k \bmod 2^k mod2k操作。
for (variable = A; variable != B; variable += C)

该代码的意义为:变量初值为A,每次循环变量的值增加C,当变量的值等于B时跳出循环。

假设进行了 x x x次循环,则有 A + x C   m o d   2 k = B A+xC \bmod 2^k = B A+xCmod2k=B。

或列成同余方程 A + x C ≡ B ( m o d 2 k ) A+xC\equiv B \pmod{2^k} A+xC≡B(mod2k)

整理得 C x ≡ B − A ( m o d 2 k ) Cx\equiv B-A \pmod{2^k} Cx≡B−A(mod2k)

  • 如果 g c d ( C , 2 k ) ∣ ( B − A ) gcd(C, 2^k)\mid (B-A) gcd(C,2k)∣(B−A),则该方程有解,通过扩展欧几里得算法求线性同余方程的解。
    -如果 g c d ( C , 2 k ) ∤ ( B − A ) gcd(C, 2^k)\nmid (B-A) gcd(C,2k)∤(B−A),则该方程无解,即无论进行几次循环,变量的值都无法等于 B B B,输出FOREVER。

【题解代码】

解法1:扩展欧几里得算法直接求解线性同余方程
cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define N 25
#define MOD(a, b) (((a)%(b)+(b))%(b)) 
typedef long long LL;
void exgcd(LL a, LL b, LL &x, LL &y, LL &g)
{
	if(b == 0)
	{
		x = 1, y = 0, g = a;
		return;
	}
	exgcd(b, a%b, y, x, g);
	y -= a/b*x;
}
int main()
{
	LL a, b, c, k, x, y, g;
	while(cin >> a >> b >> c >> k && !(a == 0 && b == 0 && c == 0 && k == 0))
	{
		exgcd(c, 1LL<<k, x, y, g);
		if((b-a)%g == 0)
			cout << MOD(x*(b-a)/g, (1LL<<k)/g) << endl;
		else
			cout << "FOREVER" << endl;
	}
	return 0;
}
解法2:先求乘法逆元再解线性同余方程
cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define N 25
#define MOD(a, b) (((a)%(b)+(b))%(b)) 
typedef long long LL;
void exgcd(LL a, LL b, LL &x, LL &y)
{
	if(b == 0)
	{
		x = 1, y = 0;
		return;
	}
	exgcd(b, a%b, y, x);
	y -= a/b*x;
}
LL gcd(LL a, LL b)
{
	if(b == 0)
		return a;
	return gcd(b, a%b);
}
LL inv(LL a, LL m)
{
	LL x, y;
	exgcd(a, m, x, y);
	return MOD(x, m);
}
int main()
{
	LL a, b, c, k, x, y, g;
	while(cin >> a >> b >> c >> k && !(a == 0 && b == 0 && c == 0 && k == 0))
	{
		g = gcd(c, 1LL<<k);
		if((b-a)%g == 0)
			cout << MOD((b-a)/g*inv(c, 1LL<<k), (1LL<<k)/g) << endl;
		else
			cout << "FOREVER" << endl;
	}
	return 0;
}
相关推荐
wuminyu7 小时前
Kafka中sendfile与mmap实现机制解析
java·linux·c语言·jvm·c++
Blockbuater_drug8 小时前
FreeSASA: 开源 SASA 计算库,pip 一条命令替代 NACCESS
c语言·开源·sasa·freesasa·溶剂可及表面积·naccess·python api
Logic1019 小时前
C语言/数据结构位运算题解:异或XOR找出蛋糕订单中的“VIP独特口味“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质
Logic10110 小时前
C语言/数据结构位运算题解:异或XOR找出飞行棋中的“独特颜色棋子“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质
Logic10112 小时前
C语言/数据动态规划题解:翻转一次子数组后的最大子数组和——四状态DP(O(n)时间O(1)空间)
c语言·数据结构·动态规划·时间复杂度·算法题·状态机dp·最大子数组和
Logic10113 小时前
C语言/数据结构字符串题解:找出DNA序列中未配对的独特序列——排序+遍历(O(nlogn))
c语言·数据结构·字符串·数组·排序·时间复杂度·算法题
Navigator_Z14 小时前
LeetCode //C - 1248. Count Number of Nice Subarrays
c语言·算法·leetcode
是隼人14 小时前
buuctf-pwn picoctf_2018_shellcode(ret2shellcode)题解(学习过程持续更新)
c语言·学习·安全·pwn入门·ctf入门
潜创微科技14 小时前
IT6520:USB-C 转 MIPI 高集成控制器,DP 1.4a 转 MIPI 单芯片搞定 4K120 显示
c语言·开发语言·低延迟·掌机·联阳
白色的北极熊16 小时前
字符转 ASCII 码
c语言