洛谷2312 解方程(數論)
阿新 • • 發佈:2018-12-18
題目
引理
秦九韶演算法:一個n次多項式的計算可以通過逆乘法分配律轉為只有n次加法+n次乘法的計算。百科走起
題解
數論 有人用高精度嗎?好東西呀! 在有上面的引理後,我們可以O(N)判定i是否為方程的解,這樣列舉個i差不多就過了。 如何判斷和是否為0呢?直接、暴力的想法就是高精計算,但這樣會T的。我們可以考慮用模,這樣就避免了爆long long。但是這樣容易出現玄學WA,最好用多個模數,降低意外出現的可能性。
有一個剪枝,假設模數為P,方程用f(x)=0來表示。 如果f(x)=0,那麼f(x+k*P)=0。反過來同樣正確。 所以如果一個數x,沒有f(x%P)=0,這個數不可能是方程的解。
程式碼
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const ll P=10007,Q=1000000007; const int MAXN=110; int n,m; ll a[MAXN],b[MAXN]; bool v[P]; int tot=0,list[MAXN]; bool check(int x,int mod,ll *t) { ll s=t[n]; for(int i=n-1;i>=0;i--) s=(s*x+t[i])%mod; return s==0; } int main() { scanf("%d%d",&n,&m); for(int i=0;i<=n;i++) { char ch=getchar();bool f=false; while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar(); while(ch>='0' && ch<='9') a[i]=(a[i]*10+(ch^48))%P,b[i]=(b[i]*10+(ch^48))%Q,ch=getchar(); if(f) a[i]=-a[i],b[i]=-b[i]; } for(int i=0;i<P;i++) if(check(i,P,a)) v[i]=true; for(int i=1;i<=m;i++) if(v[i%P] && check(i,Q,b)) list[++tot]=i; printf("%d\n",tot); for(int i=1;i<=tot;i++) printf("%d\n",list[i]); return 0; }