1. 程式人生 > >luogu2312 解方程

luogu2312 解方程

algo tin ems brush highlight strlen include %d long

題目大意

  已知多項式方程: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;
}

  

luogu2312 解方程