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;
} 
posted @ 2023-01-08 11:57  PKU_IMCOMING  阅读(8)  评论(0)    收藏  举报