zoukankan      html  css  js  c++  java
  • [NOIp 2014]解方程

    Description

    已知多项式方程:

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

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

    Input

    输入文件名为equation .in。

    输入共n + 2 行。

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

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

    Output

    输出文件名为equation .out 。

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

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

    Sample Input1

    2 10 
    1
    -2
    1

    Sample Output1

    1
    1

    Sample Input2

    2 10
    2
    -3
    1

    Sample Output2

    2
    1
    2

    Sample Input3

    2 10 
    1  
    3  
    2  

    Sample Output3

    0

    Hint

    对于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分算法:

    1、直接枚举,注意要用高精度。

    2、复杂度$O(m*n^3)$。

    70分算法:

    1、常识告诉我们这种方程求整数解不会有什么正经解法,有也不是联赛内容;

    2、选$k$个质数$p$,并让系数都对$p$取模,然后把$1$到$m$一个个带入验证看是不是为$0$。如果对于一个$x$,在所有取模意义下都满足方程,我们就认为这个$x$是原方程的一个解;

    3、一个模数不够就多取几个质数,一般取到$5$就可以了;

    4、因为没有了高精度,所以复杂度为$O(m*n*s)$, $s$为质数个数。

    100分算法:

    1、 $70$分做法的基础上,发现模数$p$如果取得比较小,会有个有用的信息:$x$取值$x_0$的答案和取值$x_0+p$的答案是一样的;实际上基于一个模同余式引理: $f(x)≡0(mod p)$,则$f(x+p)≡0(mod p)$

    2、所以我们只需要预处理出$x$取值$0$~$p-1$时候的答案,再枚举$1$~$m$就可以直接查询了。 

     1 //It is made by Awson on 2017.9.21
     2 #include <set>
     3 #include <map>
     4 #include <cmath>
     5 #include <ctime> 
     6 #include <queue>
     7 #include <stack>
     8 #include <string>
     9 #include <cstdio>
    10 #include <vector>
    11 #include <cstdlib>
    12 #include <cstring>
    13 #include <iostream>
    14 #include <algorithm>
    15 #define Min(a, b) ((a) < (b) ? (a) : (b))
    16 #define Max(a, b) ((a) > (b) ? (a) : (b))
    17 #define LL long long
    18 using namespace std;
    19 const int N = 100;
    20 const int M = 1000000;
    21 const int p[10] = {
    22     1007, 10007, 12347, 12349, 100017, 111647, 19720308, 19750920, 19981117, 20150208
    23 };
    24 
    25 int n, m;
    26 LL a[N+5][10];
    27 bool vis[M+5];
    28 int ans[M+5], cnt = 0;
    29 
    30 void getdata(int x) {
    31     char ch = N;
    32     bool flag = 0;
    33     while ((ch < '0' || ch > '9') && (ch != '-')) ch = getchar();
    34     if (ch == '-') {
    35         flag = 1;
    36         ch = getchar();
    37     }
    38     while (ch >= '0' && ch <= '9') {
    39         for (int i = 0; i < 10; i++) a[x][i] = (a[x][i]*10+ch-48) % p[i];
    40         ch = getchar();
    41     }
    42     if (flag) for (int i = 0; i < 10; i++) a[x][i] *= -1;
    43 }
    44 bool check2(int x, int kk) {
    45     LL v = a[n][kk];
    46     for (int i = n-1; i >= 0; i--)
    47         v = (v*x+a[i][kk])%p[kk];
    48     if (v) {
    49         int t = x;
    50         while (t <= m) {
    51             vis[t] = 1;
    52             t += p[kk];
    53         }
    54         return false;
    55     }
    56     return true;
    57 }
    58 bool check(int x) {
    59     if (vis[x]) return false;
    60     for (int i = 0; i <10; i++)
    61         if (!check2(x, i)) return false;
    62     return true;
    63 }
    64 void work() {
    65     for (int i = 0; i <= n; i++)
    66         getdata(i);
    67     for (int i = 1; i <= m; i++)
    68         if (check(i)) ans[++cnt] = i;
    69     printf("%d
    ", cnt);
    70     for (int i = 1; i <= cnt; i++)
    71         printf("%d
    ", ans[i]);
    72 }
    73 
    74 int main() {
    75     while (~scanf("%d%d", &n, &m))
    76         work();
    77     return 0; 
    78 }
  • 相关阅读:
    [python] 类组合与聚合关系
    [python] 伪私有属性,防止变量名冲突
    [vim] 配置文件之常用命令模式
    [VIM] 编辑器---多行注释和取消注释及多行复制和黏贴
    [Visual Studio Code] 执行python
    [C] 编译器codeblocks安装注意
    字符串全排列
    集合全量子集提取
    random函数详解
    Solr常用命令总结
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/7566889.html
Copyright © 2011-2022 走看看