【NOIP2014提高组】解方程

题目传送门:https://www.luogu.org/problem/show?pid=2312 (习惯性放洛谷的链接)

这一题看起来数据范围巨大无比,需要使用各种玄学方法,看了题解后整个人懵逼了....

对于30%的数据,0<n2|ai|100an!=0m<100

该数据范围直接高精度,在[1m]的范围内暴力枚举即可。时间复杂度为O(nmlen2),其中len表示高精度计算过程中数字的位数。

对于50%的数据:0<n<=100,|ai|<=10100,an0,m<100

我们考虑用秦九昭算法对计算进行加速,秦九昭算法思路如图:

 

该算法目的为在求一元n次多项式的值时,将求值需要经过n2次乘法和n次加法降低至n次乘法和n次加法。

通过此方法化简,时间复杂度被降低一个len。即可拿到50分。

对于100%的数据:0<n100|ai|1010000an0,m<1000000

我们考虑将高精度的过程去掉。

考虑到同余的某些性质,我们可以对方程的两边对p取模(p为质数),若x满足(n0aixi)=0,则其必然满足n0aixi ≡ 0 (mod p)。

根据同余性质,可将其进一步化简为n0(aiximodp)0(modp),借助该方法,在枚举x值的过程中便不需要使用高精度计算了。

如果逆着推上面的式子,会发现存在有x,使得n0(aiximodp)0(modp),但(n0aixi)0。为了避免推出不可行解,首先p尽可能地取大,其次是多选几个p分别进行取模,降低通过逆定理求出错误的x的概率(我比较懒只对一个大质数取模,结果过掉了)

复制代码
 1 #include<bits/stdc++.h>
 2 #define M 2000000
 3 #define MOD 100000007
 4 #define L long long
 5 using namespace std;
 6 L rd(){
 7     int zf=1; char c; L k=0;
 8     for(c=getchar();!isdigit(c);c=getchar()) if(c=='-') zf=-1;
 9     for(;isdigit(c);c=getchar()) k=(k*10+c-'0')%MOD;
10     return k*zf;
11 }
12 L a[M]={0},n,m,p[M]={0},ans=0;
13 bool check(int x){
14     L sum=0;
15     for(int i=n;i>=0;i--)
16     sum=(a[i]+sum+MOD)*x%MOD;
17     return sum==0;
18 }
19 int main(){
20     cin>>n>>m;
21     for(int i=0;i<=n;i++) a[i]=rd();
22     for(int i=1;i<=m;i++) if(check(i)){
23         ans++; p[i]=1;
24     }
25     printf("%d\n",ans);
26     for(int i=1;i<=m;i++) if(p[i])
27     printf("%d\n",i);
28 }
复制代码

 

posted @   AlphaInf  阅读(482)  评论(2编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示