Google APAC Test 2016 Not So Random 矩阵快递幂(logN复杂度)
2016-05-10 15:23
405 查看
Problem
There is a certain "random number generator" (RNG) which takes one nonnegative integer as input and generates another nonnegative integer as output. But you know that the RNG is really not
very random at all! It uses a fixed number K, and always performs one of the following three operations:
with probability A/100: return the bitwise AND of the input and K
with probability B/100: return the bitwise OR of the input and K
with probability C/100: return the bitwise XOR of the input and K
(You may assume that the RNG is truly random in the way that it chooses the operation each time, based on the values of A, B, and C.)
You have N copies of this RNG, and you have arranged them in series such that output from one machine will be the input for the next machine in the series. If you provide X as
an input to the first machine, what will be the expected value of the output of the final machine in the series?
and C. Respectively, these denote the number of machines, the initial input, the fixed number with which all the bitwise operations will be performed (on every machine), and 100 times the probabilities of the bitwise AND, OR, and XOR operations.
if it is within an absolute or relative error of 10-9 of the correct answer. See the FAQ for an explanation of what
that means, and what formats of real numbers we accept.
0 ≤ A ≤ 100.
0 ≤ B ≤ 100.
0 ≤ C ≤ 100.
A+B+C = 100.
题目大意:对于一个“随机数生成器”,给定
,输出的结果
可能有三种,①
②
③
。求重复操作
次,最后得到的结果的期望值。
思路:首先理解求的是什么——期望,即:
。所以要求解问题,就要知道
有哪些可能的取值,并计算其概率。但是可能的取值太多,计算概率也很麻烦,所以要寻找突破口——位运算。因为提供的运算都是位运算:按位与、按位或、按位异或,并且每一个bit都是相互独立的。因此第一反应应该是将问题分解为逐位求期望。则问题转化为:
。所以我们只需要求每一个bit贡献的期望,然后累加到结果中就行了。
有了以上思路,接下来就是怎么求解某个bit的期望了。不失一般性,以下对第
位进行分析。在整个运算中,
是不变的,来一个输入变量
,可以很快求出结果为0、为1的概率。如下:
有了上述一轮运算的状态迁移后,我们可以写出状态的递推关系:
由此可得状态转移矩阵:
对给定的输入
,初始概率可以根据bit为0或者为1求得,进行
轮则对状态转移矩阵求
次幂即可,使用快速幂复杂度为
。AC代码如下:
总结:首先要理解题意,将要解决的原始问题想清楚,再从算法的角度去考虑问题。对于有限的状态转换,可以使用状态转移矩阵来表示,然后将重复的操作转换成矩阵连乘,还可以使用快速幂进行优化。
There is a certain "random number generator" (RNG) which takes one nonnegative integer as input and generates another nonnegative integer as output. But you know that the RNG is really not
very random at all! It uses a fixed number K, and always performs one of the following three operations:
with probability A/100: return the bitwise AND of the input and K
with probability B/100: return the bitwise OR of the input and K
with probability C/100: return the bitwise XOR of the input and K
(You may assume that the RNG is truly random in the way that it chooses the operation each time, based on the values of A, B, and C.)
You have N copies of this RNG, and you have arranged them in series such that output from one machine will be the input for the next machine in the series. If you provide X as
an input to the first machine, what will be the expected value of the output of the final machine in the series?
Input
The first line of the input gives the number of test cases, T. T test cases follow; each consists of one line with six integers N, X, K, A, B,and C. Respectively, these denote the number of machines, the initial input, the fixed number with which all the bitwise operations will be performed (on every machine), and 100 times the probabilities of the bitwise AND, OR, and XOR operations.
Output
For each test case, output one line containing "Case #x: y", where x is the test case number (starting from 1) and y is the expected value of the final output. y will be considered correctif it is within an absolute or relative error of 10-9 of the correct answer. See the FAQ for an explanation of what
that means, and what formats of real numbers we accept.
Limits
1 ≤ T ≤ 50.0 ≤ A ≤ 100.
0 ≤ B ≤ 100.
0 ≤ C ≤ 100.
A+B+C = 100.
Sample
Input | Output |
3 1 5 5 10 50 40 2 5 5 10 50 40 10 15 21 70 20 10 | Case #1: 3.0000000000 Case #2: 3.6000000000 Case #3: 15.6850579098 |
,输出的结果
可能有三种,①
②
③
。求重复操作
次,最后得到的结果的期望值。
思路:首先理解求的是什么——期望,即:
。所以要求解问题,就要知道
有哪些可能的取值,并计算其概率。但是可能的取值太多,计算概率也很麻烦,所以要寻找突破口——位运算。因为提供的运算都是位运算:按位与、按位或、按位异或,并且每一个bit都是相互独立的。因此第一反应应该是将问题分解为逐位求期望。则问题转化为:
。所以我们只需要求每一个bit贡献的期望,然后累加到结果中就行了。
有了以上思路,接下来就是怎么求解某个bit的期望了。不失一般性,以下对第
位进行分析。在整个运算中,
是不变的,来一个输入变量
,可以很快求出结果为0、为1的概率。如下:
有了上述一轮运算的状态迁移后,我们可以写出状态的递推关系:
由此可得状态转移矩阵:
对给定的输入
,初始概率可以根据bit为0或者为1求得,进行
轮则对状态转移矩阵求
次幂即可,使用快速幂复杂度为
。AC代码如下:
#include <iostream> #include <cstdio> using namespace std; void multiply(double m1[], double m2[]){ double ans[] = {0, 0, 0, 0}; ans[0] = m1[0] * m2[0] + m1[1] * m2[2]; ans[1] = m1[0] * m2[1] + m1[1] * m2[3]; ans[2] = m1[2] * m2[0] + m1[3] * m2[2]; ans[3] = m1[2] * m2[1] + m1[3] * m2[3]; for(int i = 0; i < 4; ++i) m1[i] = ans[i]; } int main(){ int tc, ca = 0; cin >> tc; while(tc--){ int n, x, k; double a, b, c; cin >> n >> x >> k >> a >> b >> c; a /= 100, b /= 100, c /= 100; /*ans0,ans1保存最终的状态*/ double ans0[] = {1, 0, 0, 1}, ans1[] = {1, 0, 0, 1}; double cur0[] = {1, a, 0, b + c}, cur1[] = {a, c, b + c, a + b}; while(n){ if(n & 1) multiply(ans0, cur0), multiply(ans1, cur1); multiply(cur0, cur0), multiply(cur1, cur1); n >>= 1; } /*按位求期望*/ int base = 1; double res = 0; while(x || k){ /*p0,p1表示初始状态为0,1的概率,c0,c1表示相应的矩阵系数*/ double p1 = x & 1 ? 1 : 0, p0 = 1 - p1; double c0, c1; if(k & 1) c0 = ans1[2], c1 = ans1[3]; else c0 = ans0[2], c1 = ans0[3]; res += (c0 * p0 + c1 * p1) * base; //求解当前bit的期望 base <<= 1, x >>= 1, k >>= 1; } printf("Case #%d: %.10lf\n", ++ca, res); } }
总结:首先要理解题意,将要解决的原始问题想清楚,再从算法的角度去考虑问题。对于有限的状态转换,可以使用状态转移矩阵来表示,然后将重复的操作转换成矩阵连乘,还可以使用快速幂进行优化。
相关文章推荐
- Django模型层Meta内部类详解
- Django urls配置
- Google深度学习笔记 Logistic Classification
- 《Go语言编程入门》视频课程开课了
- Google map api 初学
- 为韩春雨老师和他的 NgAgo-gDNA 点赞
- 为韩春雨老师和他的 NgAgo-gDNA 点赞
- 换新LOGO,58集团想从分类信息向生活服务巨头蜕变?
- 【bzoj1419】Red is good 期望dp
- django中的权限控制(form增删改)
- poj 2262 Goldbach's Conjecture -- 筛法求素数打表
- Django(一)多对一模型
- Django:URL-patterns的高级使用方式与URL传递参数
- Create a Virtual Reality Game For Google Cardboard
- golang学习第二篇 开发环境的搭建
- Golang测试技术
- 龙书(Dragon book) +鲸书(Whale book)+虎书(Tiger book)
- 【转】十条有用的 Go 技术
- Go语言学习(十三)面向对象编程-继承
- Google地图的坑SupportMapFragment.getmap() returns null