题解:AT_tenka1_2019_e Polynomial Divisors
给定 \(N\) 次多项式 \(f(x)=a_N\times x^N+a_{N-1}\times x^{N-1}+\dots+a_0\) ,请求出所有满足以下条件的质数 \(p\) :对于任意整数 \(x\) ,\(f(x)\) 都是 \(p\) 的倍数。从小到大输出。
注意到对于一个质数 \(p\),有 \(a_ix^i\equiv a_ix^{i\bmod(p-1)}\pmod p\),所以我们可以 \(O(n)\) 将 \(f(x)\) 转化为一个 \(\min(n,p-2)\) 次的多项式并判断其是否符合要求。
接下来我们对 \(a_0\) 的值进行分讨:
- 若 \(a_0\not=0\),则 \(f(0)=a_0\),所以符合条件的只有 \(a_0\) 的质因子。
- 若 \(a_0=0\),那我们设 \(g=\gcd\limits_{i=1}^na_i\),显然所有 \(g\) 是质因子是满足条件的。同时对于一些小于 \(n+1\) 的质数也有可能通过降幂改变系数让 \(p\) 是满足条件的。所以我们再暴力判断小于 \(n+1\) 的质数,并把合法的加入答案。
#include<bits/stdc++.h>
#define int long long
using namespace std;
char buf[1000005],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++)
int read(){
int x=0,f=0,c=gc();
while(!isdigit(c))f|=(c=='-'),c=gc();
while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=gc();
return f?-x:x;
}
char puf[1000005];
int ptot;
#define pc(x) (ptot==1000000?(fwrite(puf,1,1000000,stdout),ptot=0,puf[ptot++]=x):puf[ptot++]=x)
void print(int x){
if(x<0){
pc('-');
print(-x);
return;
}
if(x>9)print(x/10);
pc(x%10+'0');
}
int n,a[10005],b[10005];
vector<int>ans;
void ch(int x){
for(int i=0;i<=min(x,n);i++)b[i]=0;
for(int i=0;i<=n;i++)b[i%(x-1)]=(b[i%(x-1)]+a[i]%x+x)%x;
for(int i=0;i<=min(x,n);i++){
if(b[i])return;
}
ans.push_back(x);
}
int p[10005],tot;
bool f[100005];
void ss(){
for(int i=2;i<=10000;i++){
if(!f[i])p[++tot]=i;
for(int j=1;i*p[j]<=10000&&j<=tot;j++){
f[i*p[j]]=1;
if(i%p[j]==0)break;
}
}
}
signed main()
{
n=read();
for(int i=n;i>=0;i--)a[i]=read();
if(a[0]!=0){
int x=abs(a[0]);
for(int i=2;i*i<=x;i++){
if(x%i==0){
ch(i);
while(x%i==0)x/=i;
}
}
if(x>1)ch(x);
}
else{
ss();
int gcd=0;
for(int i=0;i<=n;i++)gcd=__gcd(gcd,a[i]);
gcd=abs(gcd);
for(int i=2;i*i<=gcd;i++){
if(gcd%i==0){
if(i>n)ans.push_back(i);
while(gcd%i==0)gcd/=i;
}
}
if(gcd>1&&gcd>n)ans.push_back(gcd);
for(int i=1;i<=tot&&p[i]<=n;i++){
ch(p[i]);
}
sort(ans.begin(),ans.end());
}
for(int x:ans)print(x),pc(10);
fwrite(puf,1,ptot,stdout);
return 0;
}