链接:https://ac.nowcoder.com/acm/problem/19877
来源:牛客网
题目描述
在一次偶然的情况下,小可可得到了一个密码箱,听说里面藏着一份古代流传下来的藏宝图,只要能破解密码就能打开箱子,而箱子背面刻着的古代图标,就是对密码的提示。经过艰苦的破译,小可可发现,这些图标表示一个数以及这个数与密码的关系。假设这个数是n,密码为x,那么可以得到如下表述: 密码x大于等于0,且小于n,而x的平方除以n,得到的余数为1。 小可可知道满足上述条件的x可能不止一个,所以一定要把所有满足条件的x计算出来,密码肯定就在其中。计算的过程是很艰苦的,你能否编写一个程序来帮助小可可呢?(题中x,n均为正整数)
输入描述:
输入文件只有一行,且只有一个数字n(1 ≤ n ≤ 2,000,000,000)。
输出描述:
你的程序需要找到所有满足前面所描述条件的x,如果不存在这样的x,你的程序只需输出一行“None”(引号不输出),否则请按照从小到大的顺序输出这些x,每行一个数。
析:根据题意,很容易就能列出一个式子 x^2 % n = 1 也就是 x^2 = k*n + 1 再变形得到 x^2 - 1 = k * n,再变形,(x+1)(x-1) = k * n,得到这个式子,我就能从中得到一些信息,(x - 1) 和 (x + 1),必然包括 n 的所有的素因子,我们可以把 n 的所有素因子分成两份,一份给 (x-1)假设是 a, 一份给 (x+1),假设是b,然后再给a 和 b 随便配系数,假设是x,y,这样得到的积一定是 n 的倍数,并且配的系数还满足ax-by=2,或者ay-bx=2,直接枚举b(假设b是相比a来说更大的数)的倍数,然后判断能不能一个整数的x。注意要使用long long ,在计算过程中可能会超过int。
代码如下:
#include <bits/stdc++.h> using namespace std; int n, m; int main(){ cin >> n; set<int> ans; for(int i = 1; i * i <= n; ++i) if(n % i == 0){ int a = i, b = n / i; // a <= b for(long long j = 0; j <= n; j += b){ if(j >= 2 && (j-2) % a == 0) ans.insert(j - 1); if(j < n && (j + 2) % a == 0) ans.insert(j + 1); } } if(ans.empty()) cout << "None" << endl; else for(auto &x : ans) cout << x << endl; return 0; }