NOIP-2014 解方程

来源:互联网 发布:淘宝裂帛旗舰店童装 编辑:程序博客网 时间:2024/06/05 04:43

题目描述

已知多项式方程:

a0+a1x+a2x2+..+anxn=0

求这个方程在[1, m ] 内的整数解(n 和m 均为正整数)

输入输出格式

输入格式:

输入文件名为equation .in。

输入共n + 2 行。

第一行包含2 个整数n 、m ,每两个整数之间用一个空格隔开。

接下来的n+1 行每行包含一个整数,依次为a0,a1,a2an

输出格式:

输出文件名为equation .out 。

第一行输出方程在[1, m ] 内的整数解的个数。

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

输入输出样例

输入样例#1:2 10 1-21输出样例#1:11输入样例#2:2 102-31输出样例#2:212输入样例#3:2 10 1  3  2  输出样例#3:0

说明

对于30%的数据:0<n<=2,|ai|<=1e2,an!=0,m<1e2

对于50%的数据:0<n<=1e2,|ai|<=1e100,an!=0,m<1e2

对于70%的数据:0<n<=1e2,|ai|<=1e10000,an!=0,m<1e4

对于100%的数据:0<n<=1e2,|ai|<=1e10000,an!=0,m<1e6

题目概要

说实话只要语文比我好的应该都看得懂题 ,我都看得懂题,还有谁看不懂

毫不谦虚地挂上自己的中考模考成绩单:

生地体:A 理综:A 文综:A 数学:A 英语:A 语文:D  总成绩:5A1D buff:全校唯一一个5A1D的学生

我想应该没有语文比我弱的了吧

思路

乍一看数据

就觉得正解应该是O(nlogm)O(mlogn)的复杂度

美好愿景

要是这题不要求求出所有的解,可以二分m求解,复杂度O(n2log2m),其中O(n2)求解一个式子,O(log2m)是二分复杂度

但是

这题要求求出所有解,必须枚举每一个解 反正我是想不出什么好方法

既然

现在m的复杂度已经确定了,再看看m=1e6,n岂不是只剩下10的生存空间了,再看看n

(°°|||)
n竟然是1e2,那么我们现在只剩下一种选择:简化复杂度

看看我们的复杂度O(n2m),其中m为1e6,这表示着关于n的复杂度必须变为O(log2n)O(n)

继续

但是我们看到,长度为n的a数组是要求我们输入的啊,所以好像没有什么方法可以把它压到线性复杂度一下吧

接着

我们发现我们只能把时间压成O(nm),那么只能在求多项式值中入手,暴力求解固然O(n2),但突然发现,有一个神奇的方法叫做秦九韶算法(与其叫算法不如叫公式)

下面给出概要:

对于一个函数

f(x)=i=0naixi
=a0+a1x+a2x2+a3x3+...+anxn
=a0+x(a1+a2x+a3x2+...+anxn1)
=a0+x(a1+x(a2+a3x+a4x2+...+anxn2))
=......
=a0+x(a1+x(a2+x(a3+x(a4+...+(an+x))...))
这样就将求解一次多项式的值
的复杂度从O(n2)降到O(n)了,于是复杂度问题就解决了

但是应该可以看到a数组是一个高精度数字

那该咋办?
专心看题解,不要乱看图

于是神奇海螺告诉我们:

这时我们就选择玄学的力量,对于高精度数,我们果断使用读入优化读入高精度,在读入优化时每独一位膜一个大质数,计算ans值时也要不停地膜大质数

至于为什么?

~(≧▽≦)/~

另外,由于我们最终复杂度为O(nm) n=1e2,m=1e6,所以最终要用到卡常技巧

看程序吧

我们惊奇地发现这个程序是可以AC的,所以

哈哈

#include<bits/stdc++.h>using namespace std;#define rg registertypedef long long ll;                   //最后千万别忘了开long long,因为这个调了一上午const int mod=1e9+7;template <typename _Tp> inline void read(_Tp &x){    char c11=getchar();x=0;bool booo=0;    while(c11<'0'||c11>'9'){if(c11=='-')booo=1;c11=getchar();}    while(c11>='0'&&c11<='9'){x=(x*10+c11-'0')%mod;c11=getchar();}   //可以试试不膜大质数的结果    if(booo)x=-x;    return ;}const int maxn=101;ll a[maxn];int st[1000005],p=0;int n,m;void init();inline bool check(int x){    rg ll sum=0;    for(rg int i=n;i>-1;--i)        sum=((a[i]+sum)*x)%mod;                         //这里也要膜大质数    return sum==0;}void work(){    for(rg int i=1;i<=m;++i)if(check(i))st[++p]=i;    check(65536);    printf("%d\n",p);for(rg int i=1;i<=p;i++)printf("%d\n",st[i]);//压行你咬我啊    return ;}int main(){            //    freopen("in","r",stdin);    freopen("1.out","w",stdout);    init();    work();    return 0;}void init(){    read(n);read(m);    for(rg int i=0;i<=n;++i)read(a[i]);}