博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

【数学】【NOIP2013】解方程

Description

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

Input Format

输入共 n+2 行。 第一行包含 2 个整数 n、m,每两个整数之间用一个空格隔开。 接下来的 n+1 行每行包含一个整数,依次为a0, a1, a2, ..., an。

Output Format

第一行输出方程在[1, m]内的整数解的个数。 接下来每行一个整数,按照从小到大的顺序依次输出方程在[1, m]内的一个整数解。

Sample Input

样例输入1
2 10
1
-2
1

样例输入2
2 10
2
-3
1

样例输入3
2 10
1
3
2

Sample Output

样例输出1
1
1

样例输出2
2
1
2

样例输出3
0

Solution

正解要用到一个性质 因为方程左边等于0 0 mod 任何数都为0
若 x % k=0 那么 (x+nk) %k =0
枚举1-k的数 作为x判断方程左边是否为0
为0则为解
而 k+1 - n的数 只要通过 前面的数+nk就可以得到
比如0+k=k 1+k=k+1; 所以我们只要枚举1 - k-1就行了
k应该选择素数 并且多组
因为可能存在x 使方程左边为k的倍数
这样mod也是0 但并不是方程的解
选择多组保证数据准确
因为a很大 读入应该用字符读 边读边%
计算方程左边的值时,可以用(秦九韶?),
我的写法是((an*x+an-1)*x+an-2)*x……)*x;
#include<cstdio>
#include<cstring>

int n,m;
int a[5][105];
int f[5][10005];
int pri[5]= {9931,9941,9949,9967,9973};
int ans[1000005],ansl;

int read()
{
    char c=getchar();
    int temp=0,f=1;
    while (c<'0'||'9'<c)
    {
        if (c=='-') f=-1;
        c=getchar();
    }
    while ('0'<=c&&c<='9')
    {
        temp=temp*10+c-'0';
        c=getchar();
    }
    return temp*f;
}

bool judge(int i)
{
    for (int t=0; t<5; t++)
    {
        if (f[t][i%pri[t]]) return false;
    }
    return true;
}

int main()
{
    n=read();
    m=read();
    for (int i=0; i<=n; i++)
    {
        char ch[10005];
        scanf("%s",ch);
        int len=strlen(ch),z=0;
        for (int t=0; t<5; t++)
        {
            if (ch[0]=='-') a[t][i]=0,z=1;
            else a[t][i]=ch[0]-'0';
        }
        for (int t=0; t<5; t++)
        {
            for (int j=1; j<=len-1; j++)
            {
                a[t][i]=(a[t][i]*10+ch[j]-'0')%pri[t];
            }
            if (z==1) a[t][i]=-a[t][i];
        }
    }
    for (int t=0; t<5; t++)
    {
        for (int x=1; x<=pri[t]; x++) //((an*x+an-1)*x+an-2)*x;
        {
            int temp=0;
            for (int i=n; i>=0; i--)
            {
                temp=(temp*x+a[t][i])%pri[t];
            }
            f[t][x%pri[t]]=temp;
        }
    }
    for (int i=1; i<=m; i++)
    {
        if (judge(i))
        {
            ans[++ansl]=i;
        }
    }
    printf("%d\n",ansl);
    for (int i=1; i<=ansl; i++) printf("%d\n",ans[i]);
}

 

 

posted @ 2017-10-18 22:12  JadeDark  阅读(203)  评论(0编辑  收藏  举报