嘘~ 正在从服务器偷取页面 . . .

UOJ156 【清华集训2015】恐怖的奴隶主 题解


UOJ156 【清华集训2015】恐怖的奴隶主 题解

题目链接:#156. 【清华集训2015】恐怖的奴隶主

题意

"A fight? Count me in!" 要打架了,算我一个。

"Everyone, get in here!" 所有人,都过来!

冷酷的酒客(Grim Patron)对战歌指挥官(Warsong Commander)的削弱感到很伤心,他打算用一道数学题来纪念战歌指挥官。

\(\left \{ u_i \right \}\) 为一数列

\[ \begin{equation} u_i = a + \frac{b}{u_{i-1}} + \frac{c}{u_{i-1}u_{i-2}} \quad (i \geq 2) \end{equation} \] 已知 \(u_0, u_1, a, b, c, n\)。保证 \(x^3 = a x^2 + b x + c\)\(3\) 个不同的正整数解。

\(u_n\)

输入格式

输入仅一行,包含 \(6\) 个整数 \(u_0, u_1, a, b, c, n\)

输出格式

输出仅一行,包含 \(1\) 个整数,保留至少 \(8\) 位至多 \(15\) 位小数。如果你的答案和我们的答案差别不超过 \(10^{-6}\),则认为正确。考虑到浮点运算本身的误差,当你的答案与真实答案差别不超过 \(10^{-6} - 10^{-8}\) 时,才能保证正确。

数据范围

对于 \(100\%\) 的数据,\(c \leq 100000\)\(\lvert u_0 \rvert \leq 1000, \lvert u_1 \rvert \leq 1000\)\(0 \leq n \leq 10^9\)

巧妙的一道题,不知道为什么差评那么多(谁想得到这种东西啊喂

首先从 \(x^3 = a x^2 + b x + c\)\(3\) 个不同的正整数解出发

\(x\) 是这个方程的某个解

一般这种题目的数列都是收敛数列,即有极限的数列。

注:数列的极限定义如下:(来自《数学分析》B.A.卓里奇)

\(A \in \mathbb{R}\) 称为数列 \(\{x_n\}\) 的极限,如果对于任何 \(\epsilon > 0\) ,都存在序号 \(N\) ,使得对于一切 \(n>N\) ,都有 \(|x_n - A| < \epsilon\)

形式化地, \[ \left(\lim\limits_{n \to \infty} x_n = A\right):= \forall \epsilon > 0 ,\exists N \in \mathbb{N},\forall n > N,(|x_n - A| < \epsilon) \]

于是,我们尝试代入 \(u_i = u_{i-1}=x\)

会发现 \(u_{i+1} = x\)嗨害嘿,原数列落入了不动点

因此 \(\lim\limits_{n \to \infty}u_n = x\) ,现在关键是怎么找到这个 \(x\) (因为有三个根嘛)

对于「 \(n \le 60\) 左右」的情况,可以暴力计算1

\(n\) 特别大的时候,我们只要将得到的数舍入

然后判断那个数是不是根即可,注意要判断其收敛趋势

时间复杂度 \(O(1)\)

代码:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdarg>
#include <cmath>
#include <iomanip>
#include <random>
using namespace std;
#define int long long
#define double long double
#define INF 0x3f3f3f3f3f3f3f3f
#define N 66

const double eps=1e-10;
int n,a,b,c;
double u[N],rd;
bool ok(int x){return ((x - a) * x - b) * x == c;}
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    cout << fixed << setprecision(15);
    cin >> u[0] >> u[1] >> a >> b >> c >> n;
    if(n > N)
    {
        for(int i=2; i<N; i++)
        {
            u[i] = a + (b + c / u[i-2]) / u[i-1];
            rd=roundl(u[i]); // 四舍五入
            if(fabs(u[i] - rd) < 0.01 && fabs(u[i-1] - rd) < 0.01)
                if(ok(rd)) return cout << rd << '\n',0;
        }
    }else
    {
        for(int i=2; i<=n; i++) u[i] = a + (b + c / u[i-2]) / u[i-1];
        cout << u[n] << '\n';
    }
    return 0;
}

参考文献


  1. https://yhx-12243.github.io/OI-transit/records/uoj156.html↩︎


文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录