1. 程式人生 > >洛谷2312 解方程(數論)

洛谷2312 解方程(數論)

題目

引理

秦九韶演算法:一個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;
}