【NOIP2014提高组】解方程题解

前几天看到这道题,感觉蛮有意思,就来写篇题解吧。

题面很清楚,应该没什么理解上的问题吧

首先看到这题想到什么,最暴力的写法就是从1到 m m m枚举啊,把每个 x x x的值代入,看能否成立,但是这显然不行(不要问我怎么知道的,难道提高组的题这么水???)

首先,这题的确是得要枚举,但是不是暴力枚举,不是每次都把 x 0 , x 1 , . . . , x n x^0,x^1,...,x^n x0,x1,...,xn算出来的不然那样效率太低了。。。。。

这是就有了一个玄学的秦九韶算法:

具体的过程就是:
f ( x ) f(x) f(x)

= a 0 + a 1 x + a 2 x 2 + ⋯ + a n x n =a_0+a_1x+a_2x^2+\cdots+a_nx^n =a0+a1x+a2x2++anxn

= a n x n + a i − 1 x n − 1 + ⋯ + a 1 x + a 0 =a_nx^n+a_{i-1}x^{n-1}+\cdots+a_1x+a_0 =anxn+ai1xn1++a1x+a0

= ( a n x n − 1 + a i − 1 x n − 2 + ⋯ + a 2 x + a 1 ) x + a 0 =(a_nx^{n-1}+a_{i-1}x^{n-2}+\cdots+a_2x+a_1)x+a_0 =(anxn1+ai1xn2++a2x+a1)x+a0

= ( ( a n x n − 2 + a i − 1 x n − 3 + ⋯ + a 3 x + a 2 ) x + a 1 ) x + a 0 =((a_nx^{n-2}+a_{i-1}x^{n-3}+\cdots+a_3x+a_2)x+a_1)x+a_0 =((anxn2+ai1xn3++a3x+a2)x+a1)x+a0
. \LARGE. .
. \LARGE. .
. \LARGE. .
= ( ⋯ ( ( a n x + a n − 1 ) x + a n − 2 x + ⋯ + a 1 ) x + a 0 =(\cdots((a_nx+a_{n-1})x+a_{n-2}x+\cdots+a_1)x+a_0 =(((anx+an1)x+an2x++a1)x+a0

通过这个式子我们可以知道:

对于一个n次多项式,至多做n次乘法和n次加法

就是这样喽

吐槽个东西:那天在寝室里讲到秦九韶算法,同寝一位数学班巨佬说:“这秦九韶算法这么丑,不好用。”

我:“emmmmm,反正这东西手算是真的麻烦,不如一个一个算,但是到了信息上就不一样了,一次循环就搞定了,贼方便。”

还有一个就是这题读入的问题,就是得用快读再加点奇怪的东西

const int q=1000000007;
ll read()
{
    ll sum=0;
    ll flag=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-')
        {
            flag=-1;//负数
        }
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        sum=((sum*10)+c-'0')%q;//由于a很大得取模
        c=getchar();
    }
    return sum*flag;
}

q q q最好是大质数
接下来就是完整code了!

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int twx=1000000+100;
const int q=1000000007;//取模用的大质数
int n,m;
int a[twx]={};
int sum=0;
int cnt=0;
int ans[twx];
bool t=true;//判断是否有答案
ll read()
{
    ll sum=0;
    ll flag=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-')
        {
            flag=-1;//负数
        }
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        sum=((sum*10)+c-'0')%q;//由于a很大得取模
        c=getchar();
    }
    return sum*flag;
}
bool jian(ll x)
{
	sum=0;
    for(int i=n;i>=1;i--)
    {
        sum=((a[i]+sum)*x)%q;//秦九昭算法求多项式的值
    }
    sum=(sum+a[0])%q;//再加上a[0]
    if(sum)//如果sum为0的话说明x为多项式的值,返回true
    {
        return false;
    }
    else
    {
        return true;
    }
}
void init()
{
	cin>>n>>m;
    for(int i=0;i<=n;i++)
    {
        a[i]=read();//由于数太大了,得在读入时进行一些操作
    }
}
void work()
{
    for(int i=1;i<=m;i++)
    {
        if(jian(i))//有解
        {
            t=false;//cnt为答案个数
            ans[++cnt]=i;//记录答案
        }
    }
}
void print()
{
	if(t)
    {
        cout<<0;
        exit(0);
    }
    else
    {
        cout<<cnt<<endl;
        for(int i=1;i<=cnt;i++)
        {
            cout<<ans[i]<<endl;
        }
    }
}
int main()
{
    init();
    work();
    print();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值