zoukankan      html  css  js  c++  java
  • NOIP2014/洛谷P2312 解方程

    题目描述

    已知多项式方程:

    a0+a1x+a2x^2+..+anx^n=0

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

    输入输出格式

    输入格式:

    输入文件名为equation .in。

    输入共n + 2 行。

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

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

    输出格式:

    输出文件名为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|<=100,an!=0,m<100

    对于50%的数据:0<n<=100,|ai|<=10^100,an!=0,m<100

    对于70%的数据:0<n<=100,|ai|<=10^10000,an!=0,m<10000

    对于100%的数据:0<n<=100,|ai|<=10^10000,an!=0,m<1000000

    分析

    对于30%的数据,用公式解就可以了。

    对于50%的数据,高精度?

    对于100%,m的范围不大,在这个范围内枚举,计算最后的值是否为0。要用到秦九韶算法,这样只需要做n次乘法,n次加法。但是a很大,高精度也很难表示怎么办?如果方程左面的值为0,那么方程两边同时mod一个值还是成立的。如果只mod一个值的话,答案很有可能不是正确的,因为如果这个值要是mod这个值的倍数的话,mod的值也是0。我们可以多mod几个值,那么这个数就必须满足是这几个值的最小公倍数的倍数才能在mod之后都为0,否则的话这个数就是0。但是前一种情况机率还是很小的,因为如果模数都取质数的话最小公倍数就是这几个数的乘积,还是很大的。但是这样的话时间复杂度是O(n*m)的,会超时的。如果一个数x mod p !=0 的话,那么x+p mod p!=0,这样就可以少计算一些无用的数。这样的话应该能通过官方数据。

    关于秦九韶算法a[0]是否要乘以x,从公式上来看是不需要的,但是如果到最后结果如果是0的话就算乘以x之后还是0,对结果没有什么太大的影响,而且好记,代码短(lazy!)。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=1000010;
    const int mo1=99991;
    const int mo2=998244353;
    const int mo3=1e9+7;
    int n,m,cnt,a[N],b[N],c[N],ans[N]; bool vis[N];
    inline void read(int i){
        ll x1=0,x2=0,x3=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){
            x1=(x1*10+ch-'0')%mo1;
            x2=(x2*10+ch-'0')%mo2;
            x3=(x3*10+ch-'0')%mo3;
            ch=getchar();
        }
        a[i]=x1*f;b[i]=x2*f;c[i]=x3*f;
    }
    inline bool calc1(int x){
        ll sum=0;
        for(int i=n;i>=0;--i)
            sum=((a[i]+sum)*x)%mo1;
        return !sum;
    }
    inline bool calc2(int x){
        ll sum1=0,sum2=0;
        for(int i=n;i>=0;--i){
            sum1=((b[i]+sum1)*x)%mo2;
            sum2=((c[i]+sum2)*x)%mo3;
        }
        return (!sum1)&&(!sum2);
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=0;i<=n;++i) read(i);
        for(int i=1;i<=mo1;++i)
        if(calc1(i)){
            for(int j=i;j<=m;j+=mo1)
            if(calc2(j)) vis[j]=1;
        }
        for(int i=1;i<=m;++i) if(vis[i]) ans[++cnt]=i;
        printf("%d
    ",cnt);
        for(int i=1;i<=cnt;++i) printf("%d
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    iframe嵌套
    fiddler——一款莱斯的抓包工具
    工程代码规范和更新规范
    新项目新工作空间新仓库新setting文件
    quartz-job实现实时或定时发送短信任务
    quartz-job实现定时任务配置
    quartz开源作业调度框架的配置
    Confluence 6 让一个空间可以公众访问
    Confluence 6 管理和恢复空间管理权限
    Confluence 6 指派和撤销空间权限
  • 原文地址:https://www.cnblogs.com/huihao/p/7807979.html
Copyright © 2011-2022 走看看