【题解】NOIP-2014 解方程

题目描述

已知多项式方程:

a0+a1x+a2x2+..+anxn=0 a 0 + a 1 x + a 2 x 2 + . . + a n x n = 0

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

输入输出格式

输入格式:

输入文件名为equation .in。

输入共n + 2 行。

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

接下来的n+1 行每行包含一个整数,依次为 a0 a 0 , a1 a 1 , a2 a 2 an a n

输出格式:

输出文件名为equation .out 。

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

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

输入输出样例

输入样例#1:

2 10 
1
-2
1

输出样例#1:

1
1

输入样例#2:

2 10
2
-3
1

输出样例#2:

2
1
2

输入样例#3:

2 10 
1  
3  
2  


输出样例#3:

0

说明

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

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

对于70%的数据: 0<n<=1e2,|ai|<=1e10000,an!=0,m<1e4 0 < n <= 1 e 2 , | a i | <= 1 e 10000 , a n ! = 0 , m < 1 e 4

对于100%的数据: 0<n<=1e2,|ai|<=1e10000,an!=0,m<1e6 0 < n <= 1 e 2 , | a i | <= 1 e 10000 , a n ! = 0 , m < 1 e 6

题目概要

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

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

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

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

思路

乍一看数据

就觉得正解应该是 O(nlogm) O ( n l o g m ) O(mlogn) O ( m l o g n ) 的复杂度

美好愿景

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

但是

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

既然

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

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

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

继续

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

接着

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

下面给出概要:

对于一个函数

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

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

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

于是神奇海螺告诉我们:

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

至于为什么?

~(≧▽≦)/~

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

看程序吧

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

哈哈

#include<bits/stdc++.h>
using namespace std;
#define rg register
typedef 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]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值