题意
John likes to learn esoteric programming languages. Recently he discovered the probabilistic programming language Java2K. Built-in functions of Java2K have only a certain probability to do whatever you intend them to do. The Java2K programming is very hard, so John designed a much simpler language for training: Java2016. Built-in operators of Java2016 are deterministic, while their operands are random. Each value in Java2016 is a positive integer in the range 0::255, inclusive. Java2016 supports six operators of three precedencies:
- ⟨expression⟩ ::= ⟨expression⟩ ‘min’ ⟨sum⟩ | ⟨expression⟩ ‘max’ ⟨sum⟩ | ⟨sum⟩
- ⟨sum⟩ ::= ⟨sum⟩ ‘+’ ⟨term⟩ | ⟨sum⟩ ‘-’ ⟨term⟩ | ⟨term⟩
- ⟨term⟩ ::= ⟨term⟩ ‘*’ ⟨factor⟩ | ⟨term⟩ ‘/’ ⟨factor⟩ | ⟨factor⟩
- ⟨factor⟩ ::= ‘(’ ⟨expression⟩ ‘)’ | ”?’ | ⟨macro⟩
Minimum (‘min’) and maximum (‘max’) operators are de ned as usual. Addition (‘+’), subtraction (‘-‘) and multiplication (‘*’) are de ned modulo 256. The result of the division (‘/’) is rounded towards zero. If the divider is zero, the program crashes. The argument of the operator is a result of another operator, evenly distributed random value (‘?’), or macro substitution.
For instance, the probability that \?/?/?” is evaluated to zero is 98:2%, while the probability of the crash is 0:8%.
The Java2016 program consists of zero or more macro de nitions, followed by the resulting expression. Each macro de nition has a form of
- ⟨macrodef⟩ ::= ⟨macro⟩ ‘=’ ⟨expression⟩
- ⟨macro⟩ ::= ‘a’ : : : ‘z’
The macro should be de ned before the rst use. It may not be rede ned. The macro is expanded to its de nition on each use. For instance,
a = ? max ?
(a max a) / a
is expanded to ((? max ?) max (? max ?)) / (? max ?)
.
John is going to add probabilistic constants to Java2016, so for each possible constant value he needs a program that successfully evaluates to this value with at least one-half probability. Crashes are counted toward failures.
? 表示取随机数 [0, 255]
,a … z 表示宏定义变量(每个只能唯一定义)。有加减乘除和取 max, min 操作。对于询问 c ,要求给出表达式,使得表达式所表示的值为 c 的概率大于 1/2.
解题思路
构造。
a = ? max ?
b=(a max a) / a
对于题目所指出的两个表达式,b = 1 的概率为 0.50…, b=0 的概率为 0.33…, b>1 的概率为 0.16… 。
对于如何构造 c ,应该都能够想到构造 t1 = 1, t2 = 2, t3 = 4, t4 = 8…,通过位与打印结果即可,故问题的关键在于如何保证 t1, t2, t3 … 的组合概率在 1/2 以上。
通过观察数据对 b 取 max 操作将使得 b=1, =2 的概率变大, 取 min 操作将使得 b=0, b=1 的概率变大,故交替操作可使得 b=1 的概率变大(当然,由于 b=0, b=1, b>1 的概率和不为1(存在除0非法情况),故其存在上限)。
代码
#include<bits/stdc++.h>
using namespace std;
string base[] = {
"a=? max ?",
"b=(a max a) / a",
"c=(b max b) min (b max b)",
"d=(c max c) min (c max c)",
"e=(d max d) min (d max d)",
"f=(e max e) min (e max e)" };
int main()
{
freopen("java2016.in", "r", stdin);
freopen("java2016.out", "w", stdout);
int c;
scanf("%d",&c);
if(c == 0) {
printf("?/?/?");
} else {
for(int i=0;i<6;i++)
printf("%s\n", base[i].c_str());
printf("g=f+f\n");
for(int i=1;i<7;i++)
printf("%c=%c*%c\n", char('g'+i), char('f'+i), char('g'));
bool flg = 0;
for(int i=0;c;i++) {
if(c % 2) {
if(flg) printf("+");
printf("%c", char('f'+i));
flg = true;
}
c /= 2;
}
}
}