【题解】密码箱
作者:互联网
题目描述
在一次偶然的情况下,小可可得到了一个密码箱,听说里面藏着一份古代流传下来的藏宝图,只要能破解密码就能打开箱子,而箱子背面刻着的古代图标,就是对密码的提示。经过艰苦的破译,小可可发现,这些图标表示一个数以及这个数与密码的关系。假设这个数是n,密码为x,那么可以得到如下表述:
密码x大于等于0,且小于n,而x的平方除以n,得到的余数为1。
小可可知道满足上述条件的x可能不止一个,所以一定要把所有满足条件的x计算出来,密码肯定就在其中。计算的过程是很艰苦的,你能否编写一个程序来帮助小可可呢?(题中x,n均为正整数)
输入输出格式
输入格式
一行,且只有一个数字n。(1≤n≤200000000)
输出格式
你的程序需要找到所有满足前面所描述条件的x,如果不存在这样的x,你的程序只需输出一行“None”(引号不输出),否则请按照从小到大的顺序输出这些x,每行一个数。
输入输出样例
输入样例
12
输出样例
1
5
7
11
题解
n很大,所以直接暴力枚举x会爆。我们可以从减少枚举x的次数出发。
如题,x²≡1(mod n),即x²-1≡0(mod n),可以得到n|(x²-1),运用初中就教的平方差公式得n|(x-1)(x+1)。
此时我们可以设n=ab,则a|(x-1),b|(x+1)或a|(x+1),b|(x-1)。我们可以用根号n的时间复杂度来枚举a,得到b,然后用b来枚举这两种情况下的x,找出满足条件的x并记录下来。
#include <cstdio> #include <cmath> #include <set> using namespace std; int n, srn; set<int> s; int main() { scanf("%d", &n); srn = sqrt(n); for(register int i = 1, j; i <= srn; ++i) { if(n % i) continue; j = n / i; for(register int k = j - 1; k < n; k += j) { if((k - 1) % i) continue; s.insert(k); } for(register int k = 1; k < n; k += j) { if((k + 1) % i) continue; s.insert(k); } } while(!s.empty()) { printf("%d\n", *s.begin()); s.erase(s.begin()); } return 0; }参考程序
标签:可可,int,题解,密码箱,样例,密码,枚举,include 来源: https://www.cnblogs.com/kcn999/p/10352727.html