FZU 2037 Maximum Value Problem

题目大意:给定一个大小为n的数列,元素各不相同且均大于0,现给定max=0;求对于所有该数列的排列,max一共需要更新几次,还要求出平均更新几次,即ans/(n!)

注意:分清楚什么时候%mod


思路:从n递推到n-1

对于一个大小为n的数列,其排列由两部分组成:1.最大值在最右端  2.最大值不再最右端

对于第一部分:ans1=ans[n-1]+(n-1)!;

注意加(n-1)!的原因:ans[n-1]是对于前n-1个数的所有排列所需要的次数,因为最大值在最右端所以要+1,而又因为所有的排列都要+1,所以要加(n-1)!

对于第二部分:ans2=ans[n-1]*(n-1);

注意乘以(n-1)的原因:对于一个给定的放在最右端的数,都需要ans[n-1]次,而最右端一共有(n-1)中选择,所以要乘以(n-1)

所以有ans[i]=ans[i-1]+(i-1)!+ans[i-1]*(i-1)即ans[i]=ans[i-1]*i+(i-1)!;

易得  平均次数e[i]=e[i-1]+1.0/i;



#include <iostream>
#include <iomanip>
#define LL long long
#define N 1000000+5
#define mod 1000000007
using namespace std;

LL f[N], ans[N];
double e[N];

void done(){
	f[0] = 1;
	ans[0] = 0;
	e[0] = 0.0;
	for (int i = 1; i < N; i++){
		//预处理出阶乘
		f[i] = (f[i - 1] * i) % mod;
		ans[i] = (ans[i - 1] * i + f[i - 1]) % mod;
		e[i] = 1.0 / i + e[i - 1];
	}

}

int main()
{
	done();

	int t;
	cin >> t;
	for (int kase = 1; kase <= t; kase++){
		int n;
		cin >> n;
		cout << "Case " << kase << ":" << ' ' << ans[n] << " " << fixed << setprecision(6) << e[n] << endl;
	}
	return 0;
}


你可能感兴趣的:(FZU 2037 Maximum Value Problem)