关闭

SRM537-div1-2-KingXMagicSpells

标签: classjava
238人阅读 评论(0) 收藏 举报
分类:

题目大意:
     有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;
    }
}



0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:26204次
    • 积分:735
    • 等级:
    • 排名:千里之外
    • 原创:22篇
    • 转载:35篇
    • 译文:0篇
    • 评论:2条
    文章分类
    最新评论