传送门1
传送门2
写在前面:纯洁的污,还要恍然大污
思路:
(感觉数论一段时间不做就找不到感觉了呢)
题意就是求
x2≡1(mod n)
在[0,n]上所有的整数解
方程可化为
(x−1)(x+1)≡0(mod n)
即
n|(x−1)(x+1)
令
n=a∗b
,其中a,b就是n的正整数因子。则对于一个可行的x来说,一定至少有1对(a,b)满足
a|(x−1),b|(x+1)
或
a|(x+1),b|(x−1)
反过来说也是成立的
(至于证明,我们可以n与(x+1)(x-1)质因数分解,则{n的质因子}⊆{x+1的质因子}∪{x-1的质因子},而n的因子是(1,n)或质因子乘起来的,所以一定能找出一对符合条件的(a,b))
这样一来我们就比较容易地做到两件事,一是说明当n=1时无解(不可能有一个自然数是0的因子),否则一定有解(当x=n-1时,令a,b为1,n即可),二是
O(√n)
筛出n的因子,然后通过枚举每个因子的倍数p,然后判断p是否能为x-1或x+1,最后得出方程的解
注意:
1.可能会有重复解,所以用map判重
2.选取大于√n的因子做判断,不然会T
3.x=1是任何n的解(n>1)
代码:
#include<bits/stdc++.h>
#include<set>
using namespace std;
int n;
int a[50000],ans[1000000];
map<int,bool>mp;
main()
{
scanf("%d",&n);
if (n==1) printf("None"),exit(0);
ans[++ans[0]]=1;
for (int i=1;i<=sqrt(n);i++)
if (n%i==0) a[++a[0]]=n/i;
for (int i=1;i<=a[0];i++)
for (int j=a[i];j<=n;j+=a[i])
{
if ((j+2)%(n/a[i])==0&&j+1<=n&&!mp[j+1])
mp[j+1]=1,
ans[++ans[0]]=j+1;
if ((j-2)%(n/a[i])==0&&j-1>=0&&!mp[j-1])
mp[j-1]=1,
ans[++ans[0]]=j-1;
}
sort(ans+1,ans+ans[0]+1);
for (int i=1;i<=ans[0];i++) printf("%d\n",ans[i]);
}