noip2014解方程解题报告

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了noip2014解方程解题报告相关的知识,希望对你有一定的参考价值。

 看到大佬在写,,顺手就去看了看

简单思考后,还是只会打暴力,就去看了题解qwq

题目链接

cogs是图片,于是从bzoj上粘了一份。题目是有部分分的详细可看链接

 

3751: [NOIP2014]解方程

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 3788  Solved: 809
[Submit][Status][Discuss]

Description

 已知多项式方程:

a0+a1*x+a2*x^2+...+an*x^n=0
求这个方程在[1,m]内的整数解(n和m均为正整数)。
 

Input

第一行包含2个整数n、m,每两个整数之间用一个空格隔开。
接下来的n+1行每行包含一个整数,依次为a0,a1,a2,...,an。

Output

 第一行输出方程在[1,m]内的整数解的个数。

接下来每行一个整数,按照从小到大的顺序依次输出方程在[1,m]内的一个整数解。
 

Sample Input

2 10
2
-3
1

Sample Output

2
1
2

HINT

 

 对于100%的数据,0<n≤100,|ai|≤1010000,an≠0,m≤1000000。

 

对于30%的数据,怕是为了不让大家爆0而设定的,只需要枚举1到m所有x的可能值带进去一一检验即可。O(n^2*m)

对于50%的数据,我们可以打个高精度,枚举即可过掉,但是需要注意,此时带入求方程的值不能暴力求了,而是要用秦九韶算法来求。O(n*m*len),len表示高精度的位数

对于其他的数据,操作就比较sao了。

如果a=0,那么a%b=0,这是显然的,但是如果a%b=0,那么a=0,这显然是不对的,不过当b取很多个数的时候并且a%b=0都成立时,a“几乎”就等于0了,a不是0的概率会非常小,于是我们可以把他当做0。

那么我们就可以取几个素数,分别让ai对于他们依次取模(因为ai太大了,所以取模操作是在读入的时候完成,类似于高精度),然后枚举每一个x∈[1,m],边乘边取模,如果对于几个模数最终得到的结果都为0,那么我们认为x为当前方程解之一。

但是我们计算一下复杂度,n*m大概,而且要大于n*m。显然无法过掉100%的数据。那么我们需要再想一些方法。

我们知道,(a*b)%p==(a%p*b)%p,那么如果当前x∈[1,p[1]],并且x是方程的一个解,那么x+p[1]也是方程的一个解。

于是我们就将复杂度降了下来,至于是多少我也不会算啊...反正会远(shao)小于n*m,而如果模数取得很大,就无法实现这个优化,所以模数不能取很大,p[1]取10000左右就可以了

下面是我的代码。

技术分享
 1 #include<bits/stdc++.h>//好神奇!考场能拿50就上天了qwq 
 2 #define ll long long
 3 using namespace std;
 4 int n,m;
 5 ll a[10][105],mod[10]={0,10007,13417,16231,19441,22159,27043};
 6 void read(int x){
 7     char ch=getchar();
 8     int f=1;
 9     while(!(ch<=9&&ch>=0)){
10         if(ch==-)f=-1;
11         ch=getchar();
12     }
13     while(ch<=9&&ch>=0){
14         for(int i=1;i<=6;i++){
15             a[i][x]=a[i][x]*10+ch-0;
16             if(a[i][x]>=mod[i]){
17                 a[i][x]%=mod[i];
18             }
19         }ch=getchar();
20     }
21     for(int i=1;i<=6;i++)a[i][x]*=f;
22 }
23 int ans;
24 bool book[1000006];
25 int check(ll x,int z){
26     ll ans=a[z][n];
27     for(int i=n-1;i>=1;i--){
28         ans=(ans*x%mod[z]+a[z][i])%mod[z];
29     }return ans;
30 }
31 int main()
32 {
33     freopen("equationa.in","r",stdin);
34     freopen("equationa.out","w",stdout);
35     scanf("%d%d",&n,&m);n++;
36     for(int i=1;i<=n;i++){
37         read(i);
38     }
39     for(ll i=1;i<=min(mod[1],(ll)m);i++){
40         if(!check(i,1)){
41             for(int j=i;j<=m;j+=mod[1])book[j]=1,ans++;
42         }
43     }
44     for(ll i=1;i<=m;i++){
45         if(!book[i])continue;
46         int bo=0;
47         for(int j=2;j<=6;j++){
48             if(check(i,j)){
49                 bo=1;break;
50             }
51         }
52         if(bo)book[i]=0,ans--;
53     }
54     printf("%d\n",ans);
55     for(int i=1;i<=m;i++)if(book[i])printf("%d\n",i);
56     return 0;
57 }
View Code

 

以上是关于noip2014解方程解题报告的主要内容,如果未能解决你的问题,请参考以下文章

NOIP2014/洛谷P2312 解方程

NOIP2014 解方程

[Noip2014] 解方程

[NOIP2014]解方程

bzoj3751[NOIP2014]解方程 数论

$Noip2014/Luogu2312$ 解方程