NOIP 2014 解方程

题目描述Description

这里写图片描述

输入描述 Input Description

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

输出描述 Output Description

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

样例输入 Sample Input

2 10
1
-2
1

样例输出 Sample Output

1
1

数据范围及提示 Data Size & Hint

这里写图片描述

NOIP 2014 的压轴题qwq,求方程的解,因为 n <= 100 所以说不能用求根公式来解只能暴力遍历 1 到 m 。
直接读入 a[i] 后暴力找根即可得到30分,100分的算法,观察方程可以发现 f(x) %p == f(x+p) %p 所以说只要处理出0 到 p-1 的根然后筛掉不合法的解就好了,为了存下数,要对 a[i] 取模,因为模的数较小不能保证正确性,所以要多模几个。

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
char in[100010];
ll num[101][5];
int n,m;
ll mod[5] = {10657,10007,10739,11329,11149};
bool fin[1001000][5];
int ans[1000010];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i = 0 ; i <= n ; i ++)
    {
        scanf("%s",in);
        int l = strlen(in);
        bool flag = 1;
        for(int j = 0 ; j < l ; j ++)
        {
            if(in[j] == '-')
                flag = 0;
            else
            for(int k = 0 ; k <= 4 ; k ++)
                num[i][k] = (num[i][k] * 10 + in[j] - '0') % mod[k];
        }
        if(!flag)
            for(int k = 0 ; k <= 4 ; k ++)
                num[i][k] =  -num[i][k];
    }
    for(int k = 0 ; k <= 4 ; k ++)
    {
        for(int i = 0 ; i < mod[k] ; i ++)
        {
            ll temp = 0;
            for(int j = n ; j >= 0 ; j --)
                temp = (temp * i + num[j][k]) % mod[k];
            if(temp == 0)
                fin[i][k] = 1;
        }
    }
    for(int i = 1 ; i <= m ; i ++)
    {
        bool flag = 1;
        for(int k = 0 ; k <= 4 ; k ++)
        {
            if(!fin[i%mod[k]][k])
            {
                flag = 0;
                break;
            }
        }
        if(flag)
            ans[++ ans[0]] = i;
    }
    cout<<ans[0]<<endl;
    for(int i = 1 ; i <= ans[0] ; i ++)
        cout<<ans[i]<<endl;
    return 0;
}
//g++ 解方程.cpp -o 解方程.exe
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值