• [BZOJ3751] [NOIP2014] 解方程 (数学)


    Description

      已知多项式方程:$a_0+a_1*x+a_2*x^2+...+a_n*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|≤10^10000,an≠0,m≤1000000。 

    Source

    Solution

      考虑对等式左边整体对质数取模,这部分用秦九韶算法实现可以大大提速,并且可以避免大量的高精度运算

      假设模数为$p$,不难发现在模$p$意义下$x$与$x+kp$得到的结果一样,所以我们可以预处理出$[0,p)$的答案,推出$[1,m]$是否可能是解

      因为$p$很小会有类似哈希冲撞的事发生,所以我们可以选取多个$p$。据说是选$5$个$20000$左右的质数就可以,然而我换过好几个质数,不是$WA$就是$TLE$,QAQ

      代码里的质数是网上找的,并不清楚为什么这人的人品能那么好QAQ,$4$个质数就可以$AC$QAQ

      (方法会就行了,这道题考的不是质数的选取,质数照抄就行了)

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 char s[105][10005];
     4 int p[4] = {17389, 22349, 22367, 22369};
     5 int n, a[105], ans[1000005];
     6 bool vis[5][27005];
     7 
     8 bool check(int x)
     9 {
    10     if(!vis[0][x % 17389]) return false;
    11     if(!vis[1][x % 22349]) return false;
    12     if(!vis[2][x % 22367]) return false;
    13     if(!vis[3][x % 22369]) return false;
    14     return true;
    15 }
    16 
    17 bool is_zero(int k, int x)
    18 {
    19     long long ans = a[n];
    20     for(int i = n - 1; ~i; --i)
    21         ans = (ans * x + a[i]) % p[k];
    22     return !ans;
    23 }
    24 
    25 int main()
    26 {
    27     int m, tot = 0;
    28     scanf("%d%d", &n, &m);
    29     for(int i = 0; i <= n; ++i)
    30         scanf("%s", &s[i]);
    31     for(int i = 0; i < 4; ++i)
    32     {
    33         memset(a, 0, sizeof(a));
    34         for(int j = 0; j <= n; ++j)
    35             if(s[j][0] == '-')
    36                 for(int k = 1; s[j][k]; ++k)
    37                     a[j] = (a[j] * 10 - s[j][k] + 48 + p[i]) % p[i];
    38             else
    39                 for(int k = 0; s[j][k]; ++k)
    40                     a[j] = (a[j] * 10 + s[j][k] - 48) % p[i];
    41         for(int j = 1; j < p[i]; ++j)
    42             vis[i][j] = is_zero(i, j);
    43     }
    44     for(int i = 1; i <= m; ++i)
    45         if(check(i)) ans[++tot] = i;
    46     printf("%d
    ", tot);
    47     for(int i = 1; i <= tot; ++i)
    48         printf("%d
    ", ans[i]);
    49     return 0;
    50 }
    View Code
  • 相关阅读:
    python3-cookbook笔记:第十三章 脚本编程与系统管理
    python3-cookbook笔记:第十二章 并发编程
    python3-cookbook笔记:第十章 模块与包
    python3-cookbook笔记:第九章 元编程
    python3-cookbook笔记:第八章 类与对象
    python3-cookbook笔记:第七章 函数
    python3-cookbook笔记:第六章 数据编码和处理
    python3-cookbook笔记:第五章 文件与IO
    python中的列表推导式
    python的类属性、实例属性、类方法、静态方法
  • 原文地址:https://www.cnblogs.com/CtrlCV/p/5620082.html
Copyright © 2020-2023  润新知