luogu2312 解方程

题目大意

  已知多项式方程:a0+a1x+a2x^2+..+anx^n=0求这个方程在[1, m ] 内的整数解(n 和m 均为正整数)ai<=10^10000

题解

  枚举多个不太大的质数$p_i$,枚举$x\in[0,p_i-1]$,预处理,用秦九韶算法看看$f(x)$是否为0(f运算时取模)。多枚举几个质数进行上述操作,对于$x\in [1,m]$,若对$\forall p_i, f(x\mathrm{mod}p_i)=0$,则$x$为一个解。

  注意。如果枚举的$p_i$是个大质数,枚举$x\in[1,m]$在线判断$f(x\mathrm{mod}p_i)=0$,只能得70分。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

#define ll long long
const int P[4] = {23333, 10007, 10003, 27777};
const int TotP = 4;
const int MAX_STR_LEN = 10010;
const int MAX_N = 110;
const int MAX_M = 1000010;
const int MAX_P = 30000;
char S[MAX_N][MAX_STR_LEN];
ll A[MAX_N];
bool Mod_IsSol[MAX_P];
bool IsSol[MAX_M];
int M, N;

ll ReadMod(const char *s, const ll p)
{
    int len = strlen(s);
    int ans = 0, f = 1;
    for (int i = 0; i < len; i++)
    {
        if (s[i] == '-')
        {
            f = -1;
            continue;
        }
        ans = (ans * 10 + s[i] - '0') % p;
    }
    return ans * f;
}

bool Feq0(const ll x, const ll p, const ll *a, const int n)
{
    ll cur = 0;
    for (int i = n; i >= 0; i--)
        cur = (cur * x + a[i]) % p;
    return cur == 0;
}

void Select(const ll p)
{
    memset(Mod_IsSol, false, sizeof(Mod_IsSol));
    for (int i = 0; i <= N; i++)
        A[i] = ReadMod(S[i], p);
    for (int i = 0; i < p; i++)
        if (Feq0(i, p, A, N))
            Mod_IsSol[i] = true;
    for (int i = 1; i <= M; i++)
        if (!Mod_IsSol[i % p])
            IsSol[i] = false;
}

int main()
{
    scanf("%d%d\n", &N, &M);
    for (int i = 0; i <= N; i++)
        scanf("%s", S[i]);
    for (int i = 1; i <= M; i++)
        IsSol[i] = true;
    for (int i = 0; i < TotP; i++)
        Select(P[i]);
    int cnt = 0;
    for (int i = 1; i <= M; i++)
        cnt += IsSol[i];
    printf("%d\n", cnt);
    for (int i = 1; i <= M; i++)
        if (IsSol[i])
            printf("%d\n", i);
    return 0;
}

  

posted @ 2018-10-01 11:06  headboy2002  阅读(179)  评论(0编辑  收藏  举报