zoukankan      html  css  js  c++  java
  • 【NOIP2014】解方程

    最原始的思路(可以在 LG 上 AC 的)

      这题本身没有模数,但是我们可以造模数防止溢出。

      但是有一些数其实并不是方程的解,但它在模这个数下答案是 $0$。

      所以保险起见,我们对同一个数,求出它在两种不同模数下的答案,如果两者答案都是 $0$,那么判定这个数是解。

      从 $1$ 枚举到 $m$,对于每一个数都用 $O(n)$ 的复杂度验证是否有这个解,最后输出,复杂度 $O(n cdot m)$,有一些常数。

      该做法在无常数优化情况下 LG 上最慢的点耗时 700ms 左右。

      注意,式子里有常数项,记得要加。

    改进 1

      上面的做法在比较慢的机子只能拿到 $70$ 分,即使你用了很多常数优化。

      对于枚举到的每一个数,先判断它在方程中取模第一个数的值是否为 $0$,如果是就再判断使用第二个模数。

    改进 2

      一个一元 $n$ 次方程的不同解数量不超过 $n$。

      所以只要找到 $n$ 个解就可以直接退出枚举。

    改进 3

      我们把第一个模数 $p_1$ 缩小。具体原因如下:

      如果数 $a$ 在 $[1,p_1]$ 中,且把 $a$ 代入值不为 $0$,那么 $a+p_1,a+2p_1,...$ 都不是方程的解,因为这些数代入方程对 $p_1$ 取模的值肯定不是 $0$。

      所以我们可以选定一个合适的 $p_1$,找到在该模数下所有的解,假设某一个解为 $k$。

      那我们把 $k$,$k+p_1$,$k+2p_1$,$...$ 都放到第二个模数来验证,得到所有的解。

      当然所有数能够验证的前提是不超过 $m$。

      需要注意的是,这些解并不一定是有序的,需要排序。


    还有最后一个问题:这个 $p_1$ 该取多大呢?

      现在整个程序在程序中分成了三块:

      ① 读入:$O(n imes |a_i|)$,这里看作 $1e7$;

      ② 从 $1$ 枚举到 $p_1$ 找方程模 $p_1$ 下代入的值为 $0$ 的解,复杂度为 $O(n imes p_1)$;

      ③ 找从第二步中筛出的解按照优化 3 的方式再次验证,复杂度最大为 $O(n^2 imes frac{m}{p_1})$(在没有假解的情况下)。

      假设 $n,m$ 都取到最大,而且我们希望两项都不超过 $1e7$(常数问题)。

      那么得到的是 $10^3 le p_1 le 10^5$。

      但是 $p$ 不要往小取,因为你会无缘无故地在第一轮筛出很多假的解,拉低效率。

      所以如果想要质数,并且比较快,那么可以用 $100003$ 之类的数。

  • 相关阅读:
    dedecms5.7安装百度(ueditor)编辑器的方法
    shell多线程之进程间通信(2)
    shell多线程之进程间通信
    awk笔记
    用shell做简单的分布式计算
    C语言实现常用查找算法——二分查找
    C语言实现常用排序算法——基数排序
    C语言实现常用数据结构——堆
    C语言实现常用数据结构——图
    C语言实现常用数据结构——二叉查找树
  • 原文地址:https://www.cnblogs.com/zengpeichen/p/12628377.html
Copyright © 2011-2022 走看看