质因数递推 + n^2+1质因数个数很少:0116A

本文搬运自本人高中时期CSDN博客,若图片加载不出来,可到原文查看:https://blog.csdn.net/zhangtingxiqwq/article/details/135626247

http://47.92.197.167:5283/contest/452/problem/1

考虑能不能不独立,预处理呢?假设我们知道 a2+1=pqa^2+1=pq ,考虑有 (a+x)2+10(modp)(a+x)^2+1\equiv 0\pmod p ,一个合法的 xxpp

那我们就可以从这里开始去更新了。

在这里插入图片描述

首先,要证明的是每个数枚举到的时候都是质数

在这里插入图片描述


复杂度显然是O(能过),通过打表我们发现初始的数还算正常,后面的数会很大:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include<bits/stdc++.h>
using namespace std;
#ifdef LOCAL
#define debug(...) fprintf(stdout, ##__VA_ARGS__)
#else
#define debug(...) void(0)
#endif
#define int long long
inline int read(){int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;
ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+
(x<<3)+(ch^48);ch=getchar();}return x*f;}
#define Z(x) (x)*(x)
#define pb push_back
#define fi first
#define se second
//#define M
//#define mo
#define N 2000010
int n, m, i, j, k, T, q;
int a[N], ans[N];

signed main()
{
// #ifdef LOCAL
freopen("coins.in", "r", stdin);
freopen("coins.out", "w", stdout);
// #endif
// srand(time(NULL));
// T=read();
// while(T--) {
//
// }

ans[0] = 1e18;
for(i = 1; i <= 1e6; ++i) a[i] = i * i + 1, ans[i] = 1e18;
for(i = 1; i <= 1e6; ++i) {
if(a[i] == 1) continue;
debug("%lld : %lld\n", i, a[i]);
for(j = i + a[i]; j <= 1e6; j += a[i]) {
if(a[j] % a[i] == 0) a[j] /= a[i];
ans[j] = min(ans[j], a[i]);
}
// if(i % 100 == 0) debug(">> %lld\n", i);
}
q = read();
while(q--) {
n = read();
if(ans[n] == ans[0]) printf("-1\n");
else printf("%lld %lld\n", ans[n], (n * n + 1) / ans[n]);
}
return 0;
}

另一种玄学写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include<bits/stdc++.h>
using namespace std;
#ifdef LOCAL
#define debug(...) fprintf(stderr, ##__VA_ARGS__)
#else
#define debug(...) void(0)
#endif
#define int long long
inline int read(){int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;
ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+
(x<<3)+(ch^48);ch=getchar();}return x*f;}
#define Z(x) (x)*(x)
#define pb push_back
#define fi first
#define se second
//#define M
//#define mo
#define N 2000010
int n, m, i, j, k, T, c[N], q;

void dfs(int x, int y) {
int k = x * x + 1;
if(y != 1) c[x] = min(c[x], min(y, k / y));
if(x + y <= 1e6) dfs(x + y, y);
// debug("%lld %lld\n", k, y);
if(x + k / y <= 1e6) dfs(x + k / y, k / y);
}

signed main()
{
freopen("coins.in", "r", stdin);
freopen("coins.out", "w", stdout);
// srand(time(NULL));
// T=read();
// while(T--) {
//
// }
memset(c, 0x3f, sizeof(c));
dfs(1, 1);
q = read();
while(q--) {
n = read();
if(c[n] == c[0]) printf("-1\n");
else printf("%lld %lld\n", c[n], (n * n + 1) / c[n]);
}
return 0;
}