https://tenka1-2019.contest.atcoder.jp/tasks/tenka1_2019_e
首先所有系数\(\gcd\)的质因子一定是满足条件的。
\(p \mid f(x)\)就相当于\(f(x) \equiv 0 \pmod p\)
然后显然\(f(x) \equiv f(x\bmod p) \pmod p\)
那么\(f(x)\)膜\(p\)不管\(x\)取值如何都为\(0\)当且仅当\(f(0),f(1),\cdots f(p-1) \equiv 0 \pmod p\)
即\(f(x)\)在\(\bmod p\)下有因式\(\prod_{i=0}^{p-1} (x-i)\)。显然\(\prod_{i=0}^{p-1}(x-i) \equiv 0 \pmod p\)
这样我们就可以考虑枚举\(n\)以内的质数\(p\),然后check,但上面那个式子并不方便,我们想找到一个更简单且与其等价的因式。
与其等价的因式应该是一个\(p\)次多项式
又因为\(p\)是素数,对与\(p\)互质的数\(x\)都有\(x^{p-1} \equiv 1 \pmod p\),那么\(x^{p-1}-1 \equiv 0 \pmod p\),所以\(x^p-x \equiv 0 \pmod p\)。我们就找到了一个\((x,p)=1\)时与上面那个柿子等价的东西。
如果\((x,p) \not= 1\),\(p\)是质数,那么显然有\(p \mid x\),这种情况\(x^p-x\)还是满足要求的。
所以\(p \mid f(x)\)(不论\(x\)的取值),当且仅当\(f(x)\)有因式\(x^p-x\)。
于是枚举\(n\)以内的质数\(p\),将系数对\(p\)取模,然后暴力做除法即可。
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
typedef double db;
typedef long long ll;
typedef pair<int,int> PII;
typedef vector<int> VI;
const int N=5e4+10;
int gcd(int x,int y) {return y?gcd(y,x%y):x;}
int vis[N],ps[N],tn;
void sieve(int n) {
rep(i,2,n+1) {
if (!vis[i]) ps[tn++]=i;
for (int j=0;j<tn&&i*ps[j]<=n;j++) {
vis[i*ps[j]]=1;
if (i%ps[j]==0) break;
}
}
}
int a[N],n;
bool check(int p) {
if (a[0]%p) return false;
static int f[N];
rep(i,0,n+1) f[i]=(a[i]%p+p)%p;
per(i,0,n-p+1) {
int j=i+p;
f[i+1]=(f[i+1]+f[j])%p;
f[j]=0;
}
rep(i,0,n+1) if (f[i]) return false;
return true;
}
set<int> ans;
int main() {
#ifdef LOCAL
freopen("a.in","r",stdin);
#endif
scanf("%d",&n),sieve(n);
int g=0;
per(i,0,n+1) scanf("%d",&a[i]),g=gcd(g,abs(a[i]));
for (int i=2;i*i<=g;i++) {
if (g%i==0) {
ans.insert(i);
while (g%i==0) g/=i;
}
}
if (g!=1) ans.insert(g);
rep(i,0,tn) if (check(ps[i])) ans.insert(ps[i]);
for (auto p:ans) printf("%d\n",p);
return 0;
}