洛谷2312 解方程(数论)

版权声明:本文为博主原创文章,未经博主允许不得转载,除非先点了赞。 https://blog.csdn.net/A_Bright_CH/article/details/83473734

题目

洛谷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;
}

猜你喜欢

转载自blog.csdn.net/A_Bright_CH/article/details/83473734