B-不可思议

链接:https://ac.nowcoder.com/acm/contest/6220/B
来源:牛客网

在这里插入图片描述
在这里插入图片描述
备注:

输入数据包含5个整数,n,seed1,seed2,seed3,x.
树的信息生成伪代码如下
//1/
定义边集数组u[],v[] //u[i],v[i]表示第i条边的两个端点
定义变量seed4
定义循环变量i从1到n-1
循环体开始
seed4=(seed1+seed2)%998244353*seed3%998244353;
u[i]=i+1;
v[i]=(seed4%i)+1;
seed3=seed2;
seed2=seed1;
seed1=seed4;
循环体结束
//1/
询问信息生成伪代码如下,顺带一提,第一次询问的x会在输入中给出
//2/
定义变量lastans,初始值为0
定义变量ret,初始值为0
定义变量y,初始值为0 //含义见题干
定义函数ans(x,y),返回值为对数对(x,y)这组询问的答案 //这里“询问”的含义见题干
定义变量z
定义循环变量i从1到n
循环体开始
z=ans(x,y);
ret=(ret+z)%998244353;
lastans=z;
x=((x+lastans)^ret)%n+1;
y=lastans;
循环体结束
//2/
输出一个整数,表示答案。
n<=105,seed1,seed2,seed3<=109,x<=n
保证构造出的数据合法。

通过读他的备注得知树生成的伪代码将其改写:

    for(int i=1; i<=n-1; i++)
        {
            long long seed4=(seed1+seed2)%998244353*seed3%998244353;
            long long u=i+1,v=(seed4%i)+1;
            f[u]=v;
            seed3=seed2;
            seed2=seed1;
            seed1=seed4;
        }

然后套用他的询问结果:

        for(int i=1; i<=n; i++)
        {
            long long z=ans(x,y);
            ret=(ret+z)%998244353;
            lastans=z;
            x=((x+lastans)^ret)%n+1;
            y=lastans;
        }

然后通过编写ans(x,y)函数即可得出结果。

- 本题就是一个树从x节点访问到根节点,只存在一条路径,所以利用并查集的性质一直访问父节点求值即可

Code:

class Solution
{
public:
    /**
     *
     * @param n int整型
     * @param seed1 long长整型
     * @param seed2 long长整型
     * @param seed3 long长整型
     * @param x int整型
     * @return long长整型
     */
    int f[100005];
    const int mod =998244353;
    long long ans(long long x,long long y)
    {
        long long res=0;
        while(x)
        {
            res+=((y+2*x)^(y+x))%mod;
            x=f[x];
        }
        return res%mod;
    }
    long long work(int n, long long seed1, long long seed2, long long seed3, int x)
    {
        // write code here

        for(int i=1; i<=n-1; i++)
        {
            long long seed4=(seed1+seed2)%998244353*seed3%998244353;
            long long u=i+1,v=(seed4%i)+1;
            f[u]=v;
            seed3=seed2;
            seed2=seed1;
            seed1=seed4;
        }
        long long lastans=0,ret=0,y=0;
        for(int i=1; i<=n; i++)
        {
            long long z=ans(x,y);
            ret=(ret+z)%998244353;
            lastans=z;
            x=((x+lastans)^ret)%n+1;
            y=lastans;
        }
        return ret;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值