题解 P4598 [HEOI2012]Akai 的数学作业
题意:给你一个一元
我们设
将两边同时乘上
我们发现只有
而由于
所以我们只需要枚举
由于上式加起来的过程中可能 long long 都存不下,所以我们可以考虑将上式求和的过程中对答案取模一个大质数,如果多个大质数取模后的答案都为
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 105;
int n, a[N], pr[20], tot;
struct node {int p, q;} ans[N];
vector <int> vp, vq;
inline bool cmp(node a, node b) {
return a.p * b.q < a.q * b.p;
}
int ksm(int x, int y, int P) {
int res = 1;
while(y) {
if(y & 1) res = res * x % P;
x = x * x % P, y >>= 1;
}
return res;
}
bool check(int p, int q) {
for(int i = 0; i <= 11; i++) {
int sum = 0;
for(int k = 0; k <= n; k++)
sum = (sum + a[k] * ksm(p, k, pr[i]) % pr[i] * ksm(q, n - k, pr[i]) % pr[i] + pr[i]) % pr[i];
if(sum != 0) return 0;
}
return 1;
}
signed main() {
scanf("%lld", &n); for(int i = 0; i <= n; i++) scanf("%lld", &a[i]);
pr[0] = 998244353, pr[1] = 993244353, pr[2] = 993244853;
pr[3] = 998244853, pr[4] = 19260817, pr[5] = 1000000007;
pr[6] = 10000019, pr[7] = 10000079, pr[8] = 10000103;
pr[9] = 100000471, pr[10] = 100000609, pr[11] = 100000687;
int pos = 0; while(a[pos] == 0) pos++;
int a0 = abs(a[pos]), an = abs(a[n]);
for(int p = 1; p * p <= a0; p++)
if(a0 % p == 0) {
vp.push_back(p);
if(p != a0 / p) vp.push_back(a0 / p);
}
for(int q = 1; q * q <= an; q++)
if(an % q == 0) {
vq.push_back(q);
if(q != an / q) vq.push_back(an / q);
}
for(auto p : vp) for(auto q : vq) {
if(__gcd(p, q) == 1) {
if(check(p, q)) ans[++tot] = (node){p, q};
if(check(-p, q)) ans[++tot] = (node){-p, q};
}
}
if(check(0, 1)) ans[++tot] = (node){0, 1};
sort(ans + 1, ans + 1 + tot, cmp);
printf("%lld\n", tot);
for(int i = 1; i <= tot; i++)
if(ans[i].q == 1) printf("%lld\n", ans[i].p);
else printf("%lld/%lld\n", ans[i].p, ans[i].q);
return 0;
}