题解 P6261 [ICPC2019 WF]Traffic Blights
洛谷题面传送门
首先不难发现周期是
考虑一种特殊情况:
考虑将普遍的情况转化为这种情况,由于
继续优化。事实上,我们其实并不一定要让所有周期都是质数。我们发现如果一个周期是另一个周期的幂,那么我们将小的周期自动与大的周期对齐也可以转化为上一种情况,因此我们也可以取合适的
const int MAXN = 500;
const int MAXV = 100;
int n, x[MAXN + 5], r[MAXN + 5], g[MAXN + 5];
bool able[MAXN + 5][MAXV + 5];
double p[MAXN + 5];
int getmax(int x) {return (x == 2) ? 8 : ((x == 4) ? 8 : ((x == 3) ? 9 : x));}
void calc(int x) {
p[0] += 1; double prd = 1; static bool die[MAXV + 5][MAXV * 5 + 5];
memset(die, 0, sizeof(die));
for (int i = 1; i <= n; i++) {
int cnt = 0, tot = 0;
int d = __gcd(2520, r[i] + g[i]), md = (r[i] + g[i]) / d;
int rst = getmax(md), mul = rst / md;
for (int j = 0; j < md; j++) for (int k = 0; k < mul; k++) {
if (!die[rst][j + k * md]) {
if (able[i][(j * 2520 + x) % (r[i] + g[i])]) cnt++;
else die[rst][j + k * md] = 1;
tot++;
}
}
if (!tot) break;
prd = 1.0 * prd * cnt / tot;
p[i] += prd;
}
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d%d%d", &x[i], &r[i], &g[i]);
for (int i = 1; i <= n; i++) for (int j = r[i]; j < r[i] + g[i]; j++)
able[i][(j - x[i] % (r[i] + g[i]) + r[i] + g[i]) % (r[i] + g[i])] = 1;
for (int i = 0; i < 2520; i++) calc(i);
for (int i = 0; i <= n; i++) p[i] /= 2520;
for (int i = 1; i <= n + 1; i++) printf("%.10lf\n", p[i - 1] - p[i]);
return 0;
}
/*
4
0 15 49
0 13 19
0 33 63
0 27 53
*/