题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=4576
题目有意思
一开始就觉得直接DP会超时 就没敢写
可是后来他们竟然都过了....
这题因为概率和走步的顺序无关 所以先把走相同步数的先统计
相同步数统计出后二分合并,再和其他步数的合并
#include <iostream>
#include <cstdio>
#include <cstring>
#define MAXSIZE 200
#define MAX_COMMAND 100
using namespace std;
int fund[25];
int n, m, l, r;
double bina[MAX_COMMAND+5][25][MAXSIZE+5], ans[MAX_COMMAND+5][MAXSIZE+5];
double tmp[MAXSIZE+5], last[MAXSIZE];
int num[MAX_COMMAND+5];
void merge(double *x, double *y)
{
int i, j, pos;
double xx[MAXSIZE+5], yy[MAXSIZE+5];
x++; y++;
for (i = 1; i <= n; i++) { xx[i] = *x; x++; }
for (i = 1; i <= n; i++) { yy[i] = *y; y++; }
for (i = 1; i <= n; i++) tmp[i] = 0;
for (i = 1; i <= n; i++)
{
for (j = 1; j <= n; j++)
{
pos = (i+j-1)%n;
if (pos == 0) pos = n;
tmp[pos] += xx[i]*yy[j];
}
}
}
int main()
{
int i, j, k, p, q;
double output;
fund[0] = 1;
for (i = 1; i <= 20; i++) fund[i] = fund[i-1]*2;
scanf("%d %d %d %d", &n, &m, &l, &r);
while (n != 0)
{
memset(num, 0, sizeof(num));
for (i = 1; i <= MAX_COMMAND; i++)
for (j = 1; j <= MAXSIZE; j++) ans[i][j] = 0;
for (i = 1; i <= MAX_COMMAND; i++)
for (j = 0; j <= 20; j++)
for (k = 1; k <= MAXSIZE; k++) bina[i][j][k] = 0;
for (i = 1; i <= MAXSIZE; i++) last[i] = 0;
for (i = 1; i <= m; i++)
{
scanf("%d", &j);
num[j]++;
}
for (i = 1; i <= MAX_COMMAND; i++)
{
if (num[i] == 0) continue;
if ((((1+i)%n)+n)%n != 0) bina[i][0][(((1+i)%n)+n)%n] = 0.5;
else bina[i][0][n] = 0.5;
if ((((1-i)%n)+n)%n != 0) bina[i][0][(((1-i)%n)+n)%n] += 0.5;
else bina[i][0][n] += 0.5;
for (j = 1; j <= 20; j++)
{
merge(bina[i][j-1], bina[i][j-1]);
for (k = 1; k <= n; k++) bina[i][j][k] = tmp[k];
}
p = num[i];
q = 19;
ans[i][1] = 1;
while (p != 0)
{
if (p >= fund[q])
{
merge(ans[i], bina[i][q]);
for (k = 1; k <= n; k++) ans[i][k] = tmp[k];
p -= fund[q];
}
else q--;
}
}
last[1] = 1;
for (i = 1; i <= MAX_COMMAND; i++)
{
if (num[i] == 0) continue;
merge(last, ans[i]);
for (j = 1; j <= n; j++) last[j] = tmp[j];
}
output = 0;
for (i = l; i <= r; i++) output+=last[i];
printf("%.4f\n", output);
scanf("%d %d %d %d", &n, &m, &l, &r);
}
return 0;
}