zoukankan      html  css  js  c++  java
  • [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
  • 相关阅读:
    Leetcode 191.位1的个数 By Python
    反向传播的推导
    Leetcode 268.缺失数字 By Python
    Leetcode 326.3的幂 By Python
    Leetcode 28.实现strStr() By Python
    Leetcode 7.反转整数 By Python
    Leetcode 125.验证回文串 By Python
    Leetcode 1.两数之和 By Python
    Hdoj 1008.Elevator 题解
    TZOJ 车辆拥挤相互往里走
  • 原文地址:https://www.cnblogs.com/CtrlCV/p/5620082.html
Copyright © 2011-2022 走看看