SRM537-div1-2-KingXMagicSpells

本文详细解析了如何通过模拟和独立考虑二进制位的方法,计算第K天之后房间0中鸭子数的期望值。重点在于理解鸭子数的变化模式及其在二进制表示下独立性的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


题目大意:
     有N个编号为0,1,...,N-1的房间,每个房间里有若干只鸭子,鸭子数量用int[] ducks来表示。每一天会以等概率事件发生以下两件事之一:
  • 事件一:对于每一个房间i,鸭子数ducks[i]与数组int[] s1的对应元素s1[i]做异或位运算并重新赋值给ducks[i];
  • 事件二:对于每一个房间i,该房间中的所有鸭子转移到数组int[] s2所表示的对应元素s2[i]编号房间中,s2数组中的所有元素各不相同,并且所有房间的鸭子转移是在瞬间完成的。
     问:第K天之后房间0中鸭子数的期望值是多少?
     数据规模:N和K均为[1,50],ducks[]、s1[]、s2[]中的元素的取值范围为[0, 1,000,000,000]
             

思路:
     鸭子数只存在两种变化方式:
  • 与一个整数做异或位操作
  • 不同房间鸭子数互换
     这两种变化方式存在一个特点,如果把鸭子数表示成二进制形式,那么二进制中的不同位是可以相互独立进行考虑的。这一点是解题的关键,因为这样就可以分别计算每一位在K天之后的期望值,然后得到综合值。
     由于二进制位只可能取0或1两个值,因此我们可以模拟每一天过后,每个房间的鸭子数中该位取0和1的概率分别是多少。K天之后0房间内累加鸭子数每一位的期望值乘以该二进制位代表的值,即为最终的鸭子数期望值。


Java代码:

public class KingXMagicSpells {
    public double expectedNumber(int[] ducks, int[] spellOne, int[] spellTwo, int K) {
        double res = 0.0;
        for (int i = 0; i < 31; ++i) {
            int[] sBit = new int[spellOne.length];
            double[][] p = new double[ducks.length][2];
            for (int j = 0; j < ducks.length; ++j) {
                sBit[j] = (spellOne[j] >> i) & 1;
                p[j][(ducks[j] >> i) & 1] = 1.0;
            }
            for(int k = 0; k < K; ++k){
                double[][] np= new double[ducks.length][2];
                for(int j = 0; j < ducks.length; ++j){
                    np[j][0 ^ sBit[j]] += 0.5 * p[j][0];
                    np[j][1 ^ sBit[j]] += 0.5 * p[j][1];
                    np[spellTwo[j]][0] += 0.5 * p[j][0];
                    np[spellTwo[j]][1] += 0.5 * p[j][1];
                }
                p = np;
            }
            res += p[0][1] * (1 << i);
        }
        return res;
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值