蒙特卡罗算法判定多项式p(x)q(x)=r(x)是否相等

多项式乘积问题:

问题描述:

        给定阶数分别为n、m和n+m的多项式p(x)、q(x)和 r(x)。试设计一个判定p(x)q(x)=r(x)的偏假1/2 正确的蒙特卡罗算法,并要求算法的计算时间为O(n+m)。

算法设计:

        设计一个蒙特卡罗算法,对于给定多项式p(x)、q(x)和r(x),判定p(x)q(x)=r(x)是否成立。

数据输入:

        由文件input.txt给出输入数据。第1行有3个正整数n、m、I,分别表示多项式p(x)、q(x)和 r(x)的阶数。接下来的3行,每行分别有n、m、I个实数,分别表示多项式p(x)、q(x)和 r(x)的系数。

结果输出:

        将计算结果输出到文件output.txt.若p(x)q(x)=r(x)成立,则输出“YES",否则输出“NO”。

输入文件示例:

input.txt
2 1 3
1 2 3
2 2
2 6 10 6

输出文件示例:

output.txt

YES

分析与解答:

多项式的阶为k=max{m+n, l}。随机选取k+1个实数,测试等式是否成立。

算法实现:

随机数的生成:

①.random_device
random_device 是标准库提供到一个非确定性随机数生成器,使用硬件作为随机数来源,故其调用代价较高,一般用来产生随机数种子。

②.mt19937
mt19937 是标准库提供的采用梅森旋转算法的伪随机数生成器,可以快速产生高质量的随机数。

③.uniform_real_distribution
uniform_real_distribution 用于生成指定范围的均匀分布的浮点数。

    random_device rd;//用于生成随机数种子
    mt19937 r_eng(rd());//随机数生成器
    uniform_real_distribution<double> dis(FLT_MIN, FLT_MAX);//产生在闭区间[FLT_MIN, FLT_MAX]均匀分布的浮点数

多项式的结构体:

使用结构体记录多项式的阶与系数

struct poly{//多项式
    int order;//多项式阶数
    double coefficient[ORDER];//多项式的系数
}p,q,r;

计算多项式的值:

double polyValue(poly tmp,double x){//计算多项式的值
    if(x==0) return tmp.coefficient[0];
    double result=0;
    for(int i=tmp.order;i>0;i--)
        result+=tmp.coefficient[i]*pow(x,i);
    return result+tmp.coefficient[0];
}

蒙特卡罗算法:

bool MC(){
    random_device rd;//用于生成随机数种子
    mt19937 r_eng(rd());//随机数生成器
    uniform_real_distribution<double> dis(FLT_MIN, FLT_MAX);//产生在闭区间[FLT_MIN, FLT_MAX]均匀分布的浮点数
    int k=p.order+q.order>r.order?p.order+q.order:r.order;
    for(int i=k;i>=0;i--){
        double x=dis(r_eng);
        if(!(fabs(polyValue(p,x)*polyValue(q,x)-polyValue(r,x))<1e-15))
            return false;
    }
    return true;
}

结果展示:

代码:

#include<bits/stdc++.h>
#include<random>
using namespace std;
const int ORDER=64;
 
struct poly{//多项式
    int order;//多项式阶数
    double coefficient[ORDER];//多项式的系数
}p,q,r;
 
double polyValue(poly tmp,double x){//计算多项式的值
    if(x==0) return tmp.coefficient[0];
    double result=0;
    for(int i=tmp.order;i>0;i--)
        result+=tmp.coefficient[i]*pow(x,i);
    return result+tmp.coefficient[0];
}
 
bool MC(){
    random_device rd;//用于生成随机数种子
    mt19937 r_eng(rd());//随机数生成器
    uniform_real_distribution<double> dis(FLT_MIN, FLT_MAX);//产生在闭区间[FLT_MIN, FLT_MAX]均匀分布的浮点数
    int k=p.order+q.order>r.order?p.order+q.order:r.order;
    for(int i=k;i>=0;i--){
        double x=dis(r_eng);
        if(!(fabs(polyValue(p,x)*polyValue(q,x)-polyValue(r,x))<1e-15))
            return false;
    }
    return true;
}
 
int main(){
    cin>>p.order>>q.order>>r.order;
    for(int i=p.order;i>=0;i--)
        cin>>p.coefficient[i];
    for(int i=q.order;i>=0;i--)
        cin>>q.coefficient[i];
    for(int i=r.order;i>=0;i--)
        cin>>r.coefficient[i];
    string result = MC()?("YES"):("NO");
    cout<<result<<endl;
    return 0;
}

结果:

参考资料:

[1]C++ 中生成随机数的方法总结_litanyuan的博客-CSDN博客

[2]判断两多项式之积是否等于另一多项式_剑翎吹雪的博客-CSDN博客

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值