【校内互侧】ZYF loves qaq (找规律+递推)
ZYF loves qaq(qaq)
【问题描述】ZYF 有一个骰子,但是不幸的是她并不知道骰子的英文名字,于是她打算用“QAQ”来作为题目名字。这颗骰子共有 n 面,第i 面骰子对应的数字是i。ZYF会抛下无穷多次骰子,每次骰到的数字将会累加进和里。 现在 ZYF想知道出现过的和中存在数字 m的概率。
【输入格式】
第一行一个整数 T,表示有T 组数据。 接下来 T行每行两个整数表示 n和 m。
【输出格式】
T 行,每行一个小数表示概率,保留5 位小数。
【样例输入】
2
3 5
6 10
【样例输出】
0.49794
0.28929
【数据规模及约定】
对于 20%的数据 n,m<=10。
对于 50%的数据 n,m<=100000。
对于另外 30%的数据 n<=10,m<=10^9。
对于 100%的数据 n,m<=10^9,T<=10。
_____________________________________________________________
【题解】【找规律+递推】
【通过模拟,可以发现:f[i]=(f[i-1]+f[i-2]+f[i-3]+…+f[i-m])/m,可以通过递推和维护前缀和做到O(n)】
【还有就是,当n很大时,结果就趋近于零,所以后20%可以直接输出零】
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int len=1e6+5;
int n,m,t;
double f[len];
int main()
{
freopen("qaq.in","r",stdin);
freopen("qaq.out","w",stdout);
int i,j;
scanf("%d",&t);
for(i=1;i<=t;++i)
{
scanf("%d%d",&n,&m);
if(n<=1e6)
{
m=min(m,(int)1e6);
f[0]=1; double now=01;
for(j=1;j<=m;++j)
if(j-n>0) now=(f[j-1]-f[j-n-1])/(double)n,f[j]=f[j-1]+now;
else now=f[j-1]/(double)n,f[j]=f[j-1]+now;
printf("%.5lf\n",now);
}
else printf("0.00000\n");
}
return 0;
}
既然无能更改,又何必枉自寻烦忧