向前走莫回头❤

【校内互侧】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;
}


posted @ 2016-08-19 17:16  lris0-0  阅读(91)  评论(0编辑  收藏  举报
过去的终会化为美满的财富~o( =∩ω∩= )m