The 2019 Asia Nanchang First Round Online Programming Contest (H The Nth Item)

The 2019 Asia Nanchang First Round Online Programming Contest (H The Nth Item)

在这里插入图片描述
在这里插入图片描述


题意

给定一个递归式,给定一个数字n和q次操作,每次操作将上一次的答案ans和上一次的n,(ans*ans)^n作为这次的n,并将每次的ans异或起来作为最终答案输出。

思路

根据广义斐波那契数列,我们可以得到此递归式的通项公式:
在这里插入图片描述
sqrt(17)我们可以用二次剩余求出它的值。
此时,我们可以O(log(n))的求出每一次查询的值。
显然,出题人并不愿意就这样放过我们,所以我们得找n次幂的那两坨东西的幂次的循环节,这样就能把1e18的n降下来了。
然鹅出题人。。。我们必须要O(1)的知道某一项的答案。

记n次幂中间那一坨东西为x,
易知:
在这里插入图片描述
用程序跑出来我们分别知道了那两坨东西的幂次的循环节,记为xhj(循环节),所以,n<xhj,所以,我们只需要分别预处理出来1~ xhj/100次幂的x100和1~ 100次幂的x即可O(1)的访问答案。
终于可以了。。。

据说强制在线写的有点小bug,用杜教BM+记忆化也能过。。。

坑点

哪儿不是坑点。


代码

#include <bits/stdc++.h>

#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)

using namespace std;

typedef long long ll;

ll quick_pow(ll a,ll b,ll p)
{
    ll ans=1;
    a%=p;
    while(b)
    {
        if(b&1) ans=ans*a%p;
        a=a*a%p;
        b>>=1;
    }
    return ans;
}

const int N=1e7+5;
const ll MOD=998244353;
const ll sqr17=524399943;
const ll inv2=quick_pow(2,MOD-2,MOD);
const ll num1=(3+sqr17)*inv2%MOD;
const ll num2=(3-sqr17+MOD)*inv2%MOD;
const ll mod1=249561088;
const ll mod2=29360128;
const ll inv17=quick_pow(17,MOD-2,MOD);
const ll invsqr17=quick_pow(sqr17,MOD-2,MOD);

ll arr1[105];
ll arr2[105];
ll ar1[mod1/100+5];
ll ar2[mod2/100+5];

void init()
{
    arr1[0]=1;
    arr2[0]=1;
    rep(i,1,100)
    {
        arr1[i]=arr1[i-1]*num1%MOD;
        arr2[i]=arr2[i-1]*num2%MOD;
    }
    ar1[0]=1;
    ar2[0]=1;
    rep(i,1,mod1/100+2)
    {
        ar1[i]=ar1[i-1]*arr1[100]%MOD;
    }
    rep(i,1,mod2/100+2)
    {
        ar2[i]=ar2[i-1]*arr2[100]%MOD;
    }
}

ll fun(ll n)
{
    if(n==0)return 0;
    if(n==1)return 1;
    ll n1=n%mod1;
    ll n2=n%mod2;
    return ((ar1[n1/100]*arr1[n1%100]%MOD-ar2[n2/100]*arr2[n2%100]%MOD+MOD)%MOD)*invsqr17%MOD;
}

int main()
{
    init();
    int q;
    ll n;
    scanf("%d%lld",&q,&n);
    ll ans=0;
    ll answer=0;
    while(q--)
    {
        n=(ans*ans)^n;
        ans=fun(n);
        answer^=ans;
    }
    printf("%lld\n",answer);
    return 0;
}

发布了42 篇原创文章 · 获赞 6 · 访问量 4022

猜你喜欢

转载自blog.csdn.net/qq_43383246/article/details/100680933