P4296
[AHOI2007] 密码箱
题目描述
在一次偶然的情况下,小可可得到了一个密码箱,听说里面藏着一份古代流传下来的藏宝图,只要能破解密码就能打开箱子,而箱子背面刻着的古代图标,就是对密码的提示。
经过艰苦的破译,小可可发现,这些图标表示一个数以及这个数与密码的关系。假设这个数是 \(n\),密码为 \(x\),那么可以得到如下表述: 密码 \(x\) 大于等于 \(0\),且小于 \(n\),而 \(x\) 的平方除以 \(n\),得到的余数为 \(1\)。 小可可知道满足上述条件的 \(x\) 可能不止一个,所以一定要把所有满足条件的 \(x\) 计算出来,密码肯定就在其中。计算的过程是很艰苦的,你能否编写一个程序来帮助小可可呢?
输入格式
一行,一个数字 \(n\)(\(1 \leq n \leq 2 \times 10^9\))。
输出格式
你的程序需要找到所有满足前面所描述条件的 \(x\),如果不存在这样的 \(x\),你的程序只需输出一行 None,否则请按照从小到大的顺序输出这些 \(x\),每行一个数。
样例 #1
样例输入 #1
12
样例输出 #1
1
5
7
11
暴力会TLE一个点 想办法优化
注意到等价于(x-1)*(x+1)=n*k
将n分解为a*b 则有a|(x-1) b|(x+1) 或 a|(x+1) b|(x-1)
所以枚举a (1~sqrt(n)) 再枚举k*b+1 k*b-1 取符合要求的即为x
由于要排序且可能有重复的 所以用一个set来维护即可
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n;
set<int>st;
signed main()
{
ios::sync_with_stdio(false);
cin>>n;
if(n==1)
{
cout<<"None\n";
return 0;
}
st.insert(1);
for(int i=1;i*i<=n;i++)
{
if(n%i==0)
{
int a=i,b=n/i;
for(int j=b+1;j<=n;j+=b)
if((j+1)%i==0)
st.insert(j);
for(int j=b-1;j<=n;j+=b)
if((j-1)%i==0)
st.insert(j);
}
}
set<int>::iterator it;
for(it=st.begin();it!=st.end();it++)
cout<<*it<<"\n";
return 0;
}
此生无悔入OI 来生AK IOI

浙公网安备 33010602011771号