HDU 5159 Card 一次中出现两个也叫一次

Problem - 5159

set暴力超时:

int ans = 0,si = 0;
int x, b;
void dfs(set<int>cur, int t)
{
	if (t == 0)
	{
		for (auto x : cur)
			ans += x;
		si++;
		return;
	}
	for (int i = 1; i <= x; i++)
	{
		auto s = cur;
		s.insert(i);
		dfs(s, t - 1);
	}
}

void solve(int c)
{
	ans = si = 0;
	cin >> x >> b;
	for (int i = 1; i <= x; i++)
	{
		set<int>s;
		s.insert(i);
		dfs(s, b - 1);
	}
	cout << "Case #" << c << ": ";
	printf("%.3llf\n", ans*1.0 / si);
}

signed main()
{
	//ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	int t = 1;
	cin >> t;
	for (int i = 1; i <= t; i++)
	{
		solve(i);
	}
	return 0;
}

思路:

//其实dfs已经转化了一部分问题了
//我们求总和就好了
//
// 每个数*出现*就贡献一次,然而同时出现两次也只贡献一次,正着算重复情况难处理
// 不如-> 总次数减去未出现的次数就是出现次数
//(一次中出现两个也叫一次 ,比如1 : 1 2 3 和 1 1 1 各是1次)


// 每个位置有x个选择,b个位置:
//    x^b
// 一个数每个位置都不出现 (x-1)^b
// (x^b - (x-1)^b)*(1+2+...+x) / x^b

公式化简,直接求幂会溢出

//(1-((x-1)/x)^b) * (1+x)*x/2

代码:

double ksm(double x, int y) {
	if (x == 1) return 1.0;
	double res = 1, base = x;
	while (y) {
		if (y & 1) res = (res * base);
		base = (base * base) ;
		y >>= 1;
	}
	return res;
}

int x, b;
void solve(int c)
{
	cin >> x >> b;
	
	cout << "Case #" << c << ": ";
	double tmp = (x - 1)*1.0 / x;
	double ans = (1 - ksm(tmp, b)) * (1 + x) * x / 2;
	printf("%.3llf\n", ans);
}

signed main()
{
	//ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	int t = 1;
	cin >> t;
	for (int i = 1; i <= t; i++)
	{
		solve(i);
	}
	return 0;
}

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值