zoukankan      html  css  js  c++  java
  • NOIP提高组2014——解方程

    【题面】:
    解方程

    【思路】:
    首先你会发现数据非常毒瘤,(a[i]<=10^{10000}),最开始以为要写高精度,等了要完模板之后(没错我这么辣鸡怎么会高精),才发现,根本用不着23333
    因为其(n)比较小,可以考虑(hash)的思想,把(a[i])(\%)一个大质数,就避免了高精度,具体实现就是在读入的时候:

    inline ll read(){
    	ll x=0;char c;int f=1;c=getchar();
    	while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0' && c<='9'){x = (x*10+c-48)%mod;c = getchar();}
    	return (f*x)%mod;
    }
    

    然后考虑题目,(m<=1e6)(n<=100),感觉好像可以直接枚举,对于([1,m])的整数都(check)一遍,找出符合的答案。
    但这样肯定超时,应为对于一个次数为(n)的多项式,求解时需要(frac{n(n+1)}{2})次乘法和(n)次加法,复杂度就变为了(O(nm+frac{nm(n+1)}{2})),无法承受,这个时候考虑秦九韶算法。
    秦九韶算法:对于一个多项式(a_nx^n+a_{n-1}x^{n-1}+...+a_0),可以进行如下化简:

    (a_nx^n+a_{n-1}x^{n-1}+...+a_0)
    (=(a_nx^{n-1}+a_{n-1}x^{n-2}+...+a_2x+a_1)x+a_0)
    (=((a_nx^{n-2}+a_{n-1}x^{n-3}+...+a_3x+a_2)x+a_1)x+a_0)
    (.)
    (.)
    (.)
    (=(...((a_nx+a_{n-1}x+a_{n-2}x+...+a_1)x+a_0)
    则求解一个多项式的值,首先计算最内层括号内一次多项式的值,即:
    (v_0=a_n)
    (v_1=a_nx+a_{n-1})
    然后由内向外逐层计算一次多项式的值,即
    (v_2=v_1x+a_{n-2})
    (v_3=v_2x+a_{n-3})
    (.)
    (.)
    (.)
    (v_n=v_{n-1}x+a_0)
    这样,求(n)次多项式(f(x))的值就转化为求(n)个一次多项式的值。
    结论:对于一个(n)次多项式,至多做(n)次乘法和(n)次加法。
    搬运from度娘
    然后复杂度就被成功地优化到了(O(nm)),虽然理论上还是过不了,但这样做也是正确并可以(AC)

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int mod=1000000007;
    
    inline ll read(){
    	ll x=0;char c;int f=1;c=getchar();
    	while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0' && c<='9'){x = (x*10+c-48)%mod;c = getchar();}
    	return (f*x)%mod;
    }
    
    const int MAXM = 1e6;
    const int MAXN = 105;
    ll a[MAXN];ll ans[MAXM];int num = 0;int n,m;
    
    inline bool check(ll x){//秦九韶算法 
    	ll v = a[n];
    	for(int i=n-1;i>=0;--i){
    		v = (v*x + a[i])%mod;
    	}
    	return v == 0;
    }
    
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=0;i<=n;++i){
    		a[i] = read();
    	}
    	for(ll i=1;i<=m;++i){
    		if(check(i)){
    			ans[++num] = i;
    		}
    	}
    	printf("%d
    ",num);
    	for(int i=1;i<=num;++i) printf("%d
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    python生成器和使用gevent操作协程
    python飞机大战
    python控制鼠标键盘+监听键盘
    python生成彩色二维码
    springboot+springcloud+maven相关父子项目创建
    c++求最大公约数
    java8 LocalDateTime
    nginx 代理wss
    vue 全局使用axios
    Vue3.0核心源码解读| 组件渲染:vnode 到真实 DOM 是如何转变的?
  • 原文地址:https://www.cnblogs.com/lajioj/p/9475674.html
Copyright © 2011-2022 走看看