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 }
  • 相关阅读:
    time 模块学习
    day 14 自定义模块,常用模块 time .datetime ,time 模块
    day 13 课后作业
    day 12 课后作业
    day 11课后作业
    树状数组最值
    hdu 1059 Dividing bitset 多重背包
    XVII Open Cup named after E.V. Pankratiev. XXI Ural Championship
    最长公共子序列板/滚动 N^2
    Uva 10635
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/7566889.html
Copyright © 2011-2022 走看看