大家都很强, 可与之共勉 。
话说这是一道简单爆了的难题。
【NOIP2014】解方程
已知多项式方程:
求这个方程在
输入格式
第一行包含
接下来的
输出格式
第一行输出方程在
接下来每行一个整数,按照从小到大的顺序依次输出方程在
样例一
input
2 10 1 -2 1
output
1 1
样例二
input
2 10 2 -3 1
output
2 1 2
样例三
input
2 10 1 3 2
output
0
限制与约定
对于30%的数据,
对于50%的数据,
对于70%的数据,
对于100%的数据,
时间限制:
内存限制:
先补充一个知识——秦九韶算法
目的是简化多项式运算
一般地,一元n次多项式的求值需要经过2n-1次乘法和n次加法,而秦九韶算法只需要n次乘法和n次加法。在人工计算时,一次大大简化了运算过程。
inline int F ( int* a, int x ) {
int rt = 0 ;
for ( int i = n ; ~ i ; -- i ) rt = 1LL * rt * x + a [i] ;
return rt ;
}
如此一来就不用预处理x的次幂是多少,在这一题里会异常方便。
接下来我们来说这道题
显然,若f(x)=0,则f(x)≡f(x0)≡0(mod p),其中x≡x0(0<=x0 < p)。那么如果f(x0)≡0(mod p),那么基本可以确定f(x)=0。当然如果不用p取模的话输入早就爆掉了。。那么如果p比较大的话,比如>m,那么取一个质数,基本上出错概率就很小了。
然后我们对系数取模计算的时候取模,若一个数是解,那么它在所有的质数里面的结果(取了模)都应该是0。
详见代码:
UOJ AC 了 BZOJ A不掉mmp
拿UOJ代码交又是OLE又是WA
UOJ AC
开始质数取大了T掉了两个点
# include <bits/stdc++.h>
//const int P1 = 999983, P2 = 882017, P3 = 692009 ;
const int P1 = 11261, P2 = 14843, P3 = 19997 ;
const int N = 105 ;
int n, m ;
int cnt, Ans [1000005] ;
int a1 [N], a2 [N], a3 [N], ans1 [P1], ans2 [P2], ans3 [P3] ;
inline void ReadOpt ( int k ) {
static char ss [10005] ;
bool Nagative ( false ) ;
scanf ( "%s", ss ) ;
register char* pt = ss ;
if ( *ss == '-' ) {
Nagative = true ;
pt = ss + 1 ;
}
while ( *pt ) {
a1 [k] = ( 10 * a1 [k] + *pt - 48 ) % P1 ;
a2 [k] = ( 10 * a2 [k] + *pt - 48 ) % P2 ;
a3 [k] = ( 10 * a3 [k] + *pt - 48 ) % P3 ;
++ pt ;
}
if ( Nagative ) {
a1 [k] = ( P1 - a1 [k] ) ;
a2 [k] = ( P2 - a2 [k] ) ;
a3 [k] = ( P3 - a3 [k] ) ;
}
}
inline int Cal ( int* Opt, int x, int P ) {
int rt = 0 ;
for ( int i = n ; ~ i ; -- i ) rt = ( 1LL * rt * x + Opt [i] ) % P ;
return rt ;
}
int main ( ) {
scanf ( "%d%d", & n, & m ) ;
for ( int i = 0 ; i <= n ; ++ i ) ReadOpt ( i ) ;
for ( int i = 0 ; i < P1 ; ++ i ) ans1 [i] = Cal ( a1, i, P1 ) ;
for ( int i = 0 ; i < P2 ; ++ i ) ans2 [i] = Cal ( a2, i, P2 ) ;
for ( int i = 0 ; i < P3 ; ++ i ) ans3 [i] = Cal ( a3, i, P3 ) ;
for ( register int i = 1 ; i <= m ; ++ i ) {
if ( ans1 [i % P1] || ans2 [i % P2] || ans3 [i % P3] ) continue ;
Ans [++ cnt] = i ;
}
printf ( "%d\n", cnt ) ;
for ( int i = 1 ; i <= cnt ; ++ i )
printf ( "%d\n", Ans [i] ) ;
return 0 ;
}
BZOJ AC
# include <bits/stdc++.h>
const int P1 = 11261, P2 = 14843, P3 = 19997, P4 = 21893, P5 = 22877 ;
const int N = 105 ;
int n, m ;
int cnt, Ans [1000005] ;
int a1 [N], a2 [N], a3 [N], a4 [N], a5 [N], ans1 [P1], ans2 [P2], ans3 [P3], ans4 [P4], ans5 [P5] ;
inline void ReadOpt ( int k ) {
static char ss [10005] ;
bool Nagative ( false ) ;
scanf ( "%s", ss ) ;
register char* pt = ss ;
if ( *ss == '-' ) {
Nagative = true ;
pt = ss + 1 ;
}
while ( *pt ) {
a1 [k] = ( 10 * a1 [k] + *pt - 48 ) % P1 ;
a2 [k] = ( 10 * a2 [k] + *pt - 48 ) % P2 ;
a3 [k] = ( 10 * a3 [k] + *pt - 48 ) % P3 ;
a4 [k] = ( 10 * a4 [k] + *pt - 48 ) % P4 ;
a5 [k] = ( 10 * a5 [k] + *pt - 48 ) % P5 ;
++ pt ;
}
if ( Nagative ) {
a1 [k] = ( P1 - a1 [k] ) ;
a2 [k] = ( P2 - a2 [k] ) ;
a3 [k] = ( P3 - a3 [k] ) ;
a4 [k] = ( P4 - a4 [k] ) ;
a5 [k] = ( P5 - a5 [k] ) ;
}
}
inline int Cal ( int* Opt, int x, int P ) {
int rt = 0 ;
for ( int i = n ; ~ i ; -- i ) rt = ( 1LL * rt * x + Opt [i] ) % P ;
return rt ;
}
int main ( ) {
scanf ( "%d%d", & n, & m ) ;
for ( int i = 0 ; i <= n ; ++ i ) ReadOpt ( i ) ;
for ( int i = 0 ; i < P1 ; ++ i ) ans1 [i] = Cal ( a1, i, P1 ) ;
for ( int i = 0 ; i < P2 ; ++ i ) ans2 [i] = Cal ( a2, i, P2 ) ;
for ( int i = 0 ; i < P3 ; ++ i ) ans3 [i] = Cal ( a3, i, P3 ) ;
for ( int i = 0 ; i < P4 ; ++ i ) ans4 [i] = Cal ( a4, i, P4 ) ;
for ( int i = 0 ; i < P5 ; ++ i ) ans5 [i] = Cal ( a5, i, P5 ) ;
for ( register int i = 1 ; i <= m ; ++ i ) {
if ( ans1 [i % P1] || ans2 [i % P2] || ans3 [i % P3] || ans4 [i % P4] || ans5 [i % P5] ) continue ;
Ans [++ cnt] = i ;
}
printf ( "%d\n", cnt ) ;
for ( int i = 1 ; i <= cnt ; ++ i )
printf ( "%d\n", Ans [i] ) ;
return 0 ;
}