在一次偶然的情况下,小可可得到了一个密码箱,听说里面藏着一份古代流传下来的藏宝图,只要能破解密码就能打开箱子,而箱子背面刻着的古代图标,就是对密码的提示。经过艰苦的破译,小可可发现,这些图标表示一个数以及这个数与密码的关系。假设这个数是n,密码为x,那么可以得到如下表述:
密码x大于0,且小于n,而x的平方除以n,得到的余数为1。
小可可知道满足上述条件的x可能不止一个,所以一定要把所有满足条件的x计算出来,密码肯定就在其中。计算的过程是很艰苦的,你能否编写一个程序来帮助小可可呢?(题中x,n均为正整数)
输入:输入文件只有一行,且只有一个数字n(1<=n<=2,000,000,000)。
输出:你的程序需要找到所有满足前面所描述条件的x,如果不存在这样的x,你的程序只需输出一行“None”(引号不输出),否则请按照从小到大的顺序输出这些x,每行一个数。
样例:
输入:
12
输出:
1
5
7
11
题目大意:求x2≡1(mod n)在x∈[1,n]的所有整数解.
做法:先将式子变形一下
X^2≡1(mod n) -> (x+1)(x-1)=kn(k∈Z)
对于任意解x,总有
X-1=pa
x+1=qb
或
X-1=qb
x+1=pa
其中ab=n且a<b.
分析可得x一定大于sqrt(n)小于n,a*b=n,其中之一大于sqrt(n),枚举所有可能的值,
这里注意对于每一个sqrt(n)->n内的b||a,总有一个a||b,小于sqrt(n)与其对应,所以 枚举1->sqrt(n),判断n/i可以压缩范围。
那莫我们将x+1取遍所有的b和k2,再将x?1取遍所有的b和k2即可不漏地得到所有解.
时间复杂度不会证…
1 #include<cstdio> 2 //#include<vector> 3 #include<cmath> 4 #include<algorithm> 5 //#include<queue> 6 using namespace std; 7 int n; 8 int so[100000],len; 9 //vector<int>ans; 10 int ans[100000],ls; 11 int main(){ 12 freopen("box.in","r",stdin);freopen("box.out","w",stdout); 13 scanf("%d",&n); 14 int ss=(int)sqrt(n+0.5); 15 for(int i=2;i<=ss;i++){ 16 if(n%i==0){ 17 so[++len]=n/i; 18 } 19 } 20 so[++len]=n; 21 for(int i=1;i<=len;i++){ 22 int t=so[i]; 23 for(int j=t;j<=n;j+=t){ 24 if((j+2)%(n/t)==0&&j+1!=1&&j+1<n) ans[++ls]=j+1; 25 if((j-2)%(n/t)==0&&j-1!=1) ans[++ls]=j-1; 26 } 27 } 28 printf("1\n"); 29 sort(ans+1,ans+ls+1); 30 for(int i=1;i<=ls;i++){ 31 if(i==1||ans[i]!=ans[i-1]) printf("%d\n",ans[i]); 32 } 33 //while(1); 34 }
时间: 2024-10-09 21:14:29