[ AHOI2007 ] 密码箱

洛谷P4296

洛谷的数据超级水!不用任何优化的暴力枚举都能过!

正解需要一点数学推导:

\(\because x^2\ mod\ n=1\)
\(\therefore x^2-1=(x-1)(x+1)mod\ n=1\)
则必定存在\(a,b\)满足\(a|(x-1),b|(x+1)\)\(b|(x-1),a|(x+1)\)
枚举每一个\(a\),对于每一个\(a\),枚举\(x\)

在枚举 x 的时候无需从 1 开始逐个枚举,可以直接从\(\sqrt{n}\)开始,因为任何小于 \(\sqrt{n}\) 的数字,其平方都小于 \(n\),一定不满足条件(1 除外)

但洛谷上评测时最后一个点超时。。。

另外,还可以只枚举\(x-1\)\(x+1\)\(b\)的倍数的 x ,这样每次只需要加 b ,可以减少枚举数

这种方法是可以AC的,但是当我想将上面的两种方法结合在一起时,却莫名其妙地WA了。。。为神马。。。

#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
using namespace std;

vector<int> ans;
int main()
{
	int n;
	cin>>n;
	if(n==1)
	{
		printf("None");
		return 0;
	}
	ans.push_back(1);
	const int m=sqrt(n);
	for(int a=1; a<=m; a++)
	{
		if(n%a) continue;//n 不能整除 a
		int b=n/a;

		for(int x=b-1; x<n; x+=b)
		{
			if((x-1)%a==0)
			{
				ans.push_back(x);
			}
		}
		for(int x=1; x<n; x+=b)
		{
			if((x+1)%a==0)
			{
				ans.push_back(x);
			}
		}
	}
	sort(ans.begin(),ans.end());
	for(int i=0,cnt=ans.size(); i<cnt; i++)
		if(!i || ans[i]!=ans[i-1]) printf("%d\n",ans[i]);
	return 0;
}
posted @ 2018-10-19 16:33  昤昽  阅读(208)  评论(0编辑  收藏  举报