【模拟】【打表】【120814测试】【NOIP第二次模拟赛】无聊的游戏

3.无聊的游戏(boring.pas/c/cpp)

【题目描述】

有一个很无聊的游戏,就是——根据递推公式计算数列

没错,这道题就是这么无聊!

给你数列f(0)=1, f(n)=f(n-1)^2+1 (n > 0)

求出f(n)

(既然题目已经这么无聊了,那就不让大家写高精度了,取个模好了)

【输入格式】

一个整数n

【输出格式】

一行一个整数f(n),结果对1200007取模

【样例输入】

3

【样例输出】

26

【数据规模】

10%数据 1<=n<=10

30%数据 1<=n<=10^6

100%数据 1<=n<=10^9

【时限】

1s

 

①如果你直接按题目暴力能拿30分

②遇到这种按公式,并且是由前一个推当前的(即由f[i-1]推f[i]的)那么就可以想到打表!这个也能得100分

  不过由于数据太庞大,就只能部分打表(即每隔100w打一个数,然后写到你自己程序的数组里),完了后就该写自己的程序了,直接用n/100w找到是哪个循环节,然后只需向后推n%100w次即可,这样最坏的情况也就是退了100w次!很轻松就过了

③不过要想代码简洁点,也要用到上面的打表,然后写一个程序找到循环节,也能得100分

  这个打表出来了,你想凭肉眼看出循环节,可能不大现实(除非你是神牛。。。),所以还需要借助程序,在写一个程序,把刚才的表当做输入文件,每读一个数,就hash标记一下,后面只要遇到一个已经标记的数,那么这之间必定是循环的!

具体的打表我会在后面写一个打表专题,只需在标签那里找到“打表”即可

这里我已经找出来循环节:从803开始循环,570为一个周期

C++ Code

#include<iostream>
using namespace std;

const int mod=1200007;
int n;
long long f[1500];

int main()
{
    freopen("boring.in","r",stdin);
    freopen("boring.out","w",stdout);
    cin>>n;
    int i;
    f[0]=1;
    for(i=1;i<=1500;i++)
    {
        f[i]=((f[i-1]*f[i-1])%mod+1)%mod;
        if(i==n)
        {
            cout<<f[n];
            exit(0);
        }
    }
    n=(n-802)%570;
    if(n==0)n+=570;
    n+=802;
    cout<<f[n];
    return 0;
}

 

 

posted @ 2012-08-20 19:45  jiangzh  阅读(261)  评论(0编辑  收藏  举报