bzoj3751: [NOIP2014]解方程

本文介绍了一种解决高次方程的有效方法——通过取模优化枚举过程。利用该方法可以在不使用求根公式的情况下高效寻找方程的解,并提供了一个C++实现示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

题解:

首先要知道的是高次方程无求根公式,所以解这个方程没有公式,套公式只能过30%的数据
一种方法是枚举1到m的正整数,判断行不行。
若用高精度则只能能拿50分,那如何优化呢?取模!
f ( x ) = a 0 + a 1 ∗ x + a 2 ∗ x 2 + . . + a n ∗ x n f(x)=a_0+a_1*x+a_2*x^2+..+a_n*x^n f(x)=a0+a1x+a2x2+..+anxn
f ( x ) = 0 f(x)=0 f(x)=0 f ( x ) m o d p = 0 f(x) mod p=0 f(x)modp=0 p p p为任意非 0 0 0实数)
随意试几个 p p p,若 f ( x ) m o d p f(x) mod p f(x)modp都是 0 0 0,那 x x x很有可能就是方程的解
但有几点要注意:
1。p最好是质数 2。p试得越多,p越大正确率越高,但也会慢一点点,根据实际情况自己调节
如果光是这样,理论上只能过70%的数据,可能是因为洛谷评测机快吧,这样也能过
我提供一个好一点的算法
注意到当 f ( x ) m o d p = 0 f(x) mod p=0 f(x)modp=0 f ( x + k ∗ p ) m o d p = 0 f(x+k*p) mod p=0 f(x+kp)modp=0(k为整数)
这样可以避免枚举很多无用的解

标程:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int p=33331,q=100000007,k=3333331;
int n,m,i,cnt,ans[1000003],prime[p],y;
ll a[103],b[103],aa,bb,c[103],cc;
char ch;
bool f(int p,int M,ll *t){
    ll x=t[n];
    for (int i=n-1;i>=0;i--) x=(x*p+t[i])%M;
    return x==0;
}
int main(){
    cin>>n>>m;
    for (i=0;i<=n;i++){
        aa=0,bb=0,cc=0;
        for (ch=getchar(),y=0;ch<48 || 57<ch;ch=getchar()) if (ch=='-') y=1;
        for (;48<=ch && ch<=57;ch=getchar()) aa=(((aa<<3)+(aa<<1))+(ch^48))%p,bb=(((bb<<3)+(bb<<1))+(ch^48))%q,cc=((cc<<3)+(cc<<1)+(ch^48))%k;
        a[i]=y?(p-aa)%p:aa;
        b[i]=y?(q-bb)%q:bb;
        c[i]=y?(k-cc)%k:cc;
    }
    for (i=1;i<p;i++)
        if (f(i,p,a)) prime[i]=1;
    for (i=1;i<=m;i++)
        if (prime[i%p] && f(i,q,b) && f(i,k,c)) ans[cnt++]=i;
    cout<<cnt;
    for (i=0;i<cnt;i++) printf("\n%d",ans[i]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值