HDU4979-A simple math problem.

29 篇文章 0 订阅
19 篇文章 0 订阅

A simple math problem.

                                                                    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
                                                                                              Total Submission(s): 435    Accepted Submission(s): 150


Problem Description
Dragon loves lottery, he will try his luck every week. One day, the lottery company brings out a new form of lottery called accumulated lottery. In a normal lottery, you pick 7 numbers from N numbers. You will get reward according to how many numbers you match. If you match all 7 numbers, you will get the top prize for 1 billion dollars!!! Unlike normal lottery, an M-accumulated lottery allows you to pick M numbers from N numbers. If M is big enough, this may significantly increase your possibility to win. (Of course it cost more…) 

Some people buy multiple accumulated lotteries to guarantee a higher possibility to get the top prize. Despite of this, it’s still not worthy to guarantee a top prize.Knowing this, Dragon changes his target to second tier prize.  To get a second tier prize, you need to contain all of the R numbers with M numbers picked.Given N, M and R, Dragon wants to know how many M-accumulated lotteries he needs to buy, so that he can guarantee that he can get at least the second tier prize.
 

Input
The first line of input contains only one integer T, the number of test cases.

For each case, there’s a single line contains N, M and R(1<=R<=M<=N<=8).
 

Output
Each output should occupy one line. Each line should start with "Case #i: ", with i implying the case number. For each case, just output the result with no other leading or tailing spaces.
 

Sample Input
  
  
3 2 1 1 2 2 1 2 2 2
 

Sample Output
  
  
Case #1: 2 Case #2: 1 Case #3: 1
 

Author
BJTU
 

Source
 

题意:有n个号码,每张彩票是n中选M个号码的一个组合,中奖号码是n中选r个号码的一个组合,如果买的一张彩票m个号码完整覆盖r即中奖。给出n,m,r,问至少买多少彩票可以保证中奖

解题思路:这题需要舞蹈链重复覆盖打表才能通过,打表整整花了20分钟左右


#include <iostream>      
#include <cstdio>      
#include <cstring>      
#include <string>      
#include <algorithm>      
#include <cctype>      
#include <map>      
#include <cmath>      
#include <set>      
#include <stack>      
#include <queue>      
#include <vector>      
#include <bitset>      
#include <functional>      

using namespace std;

#define LL long long      
const int INF = 0x3f3f3f3f;
const int maxn = 300005;

/*
int n, m, R, x, y, tot1, tot2;
vector<int>g[10];

struct DLX
{
	int L[maxn], R[maxn], U[maxn], D[maxn];
	int row[maxn], col[maxn], sum[maxn], ans[maxn];
	int n, m, num, cnt;
	int vis[maxn];
	void add(int k, int l, int r, int u, int d, int x, int y)
	{
		L[k] = l;   R[k] = r;   U[k] = u;
		D[k] = d;   row[k] = x;  col[k] = y;
	}
	void reset(int n, int m)
	{
		num = 0x7FFFFFFF;
		this->n = n;   this->m = m;
		for (int i = 0; i <= m; i++)
		{
			add(i, i - 1, i + 1, i, i, 0, i);
			sum[i] = 0;
		}
		L[0] = m, R[m] = 0, cnt = m + 1;
	}
	void insert(int x, int y)
	{
		int temp = cnt - 1;
		if (row[temp] != x)
		{
			add(cnt, cnt, cnt, U[y], y, x, y);
			U[D[cnt]] = cnt; D[U[cnt]] = cnt;
		}
		else
		{
			add(cnt, temp, R[temp], U[y], y, x, y);
			R[L[cnt]] = cnt; L[R[cnt]] = cnt;
			U[D[cnt]] = cnt; D[U[cnt]] = cnt;
		}
		sum[y]++, cnt++;
	}
	void Remove(int k)
	{
		for (int i = D[k]; i != k; i = D[i])
		{
			L[R[i]] = L[i];
			R[L[i]] = R[i];
		}
	}
	void Resume(int k)
	{
		for (int i = U[k]; i != k; i = U[i]) L[R[i]] = R[L[i]] = i;
	}
	int A()
	{
		int dis = 0;
		for (int i = R[0]; i != 0; i = R[i]) vis[i] = 0;
		for (int i = R[0]; i != 0; i = R[i])
			if (!vis[i])
			{
				dis++, vis[i] = 1;
				for (int j = D[i]; j != i; j = D[j])
					for (int k = R[j]; k != j; k = R[k])
						vis[col[k]] = 1;
			}
		return dis;
	}
	void Dfs(int k)
	{
		if (!R[0]) { num = min(num, k); return ; }
		else if (k + A() < num)
		{
			int now = R[0];
			for (int i = R[0]; i != 0; i = R[i])
				if (sum[now] > sum[i]) now = i;
			for (int i = D[now]; i != now; i = D[i])
			{
				ans[k] = row[i];
				Remove(i);
				for (int j = R[i]; j != i; j = R[j]) Remove(j);
				Dfs(k + 1);
				for (int j = L[i]; j != i; j = L[j]) Resume(j);
				Resume(i);
			}
		}
	}
}dlx;

int main()
{
	freopen("output.txt", "w", stdout);
	for (int n = 1; n <= 8; n++)
	{
		for (int k = 1; k <= n; k++) g[k].clear();
		for (int k = 1; k < (1 << n); k++)
		{
			int sum = 0;
			for (int p = 0; p < n; p++)
				if (k&(1 << p)) sum++;
			g[sum].push_back(k);
		}
		for (int i = 1; i <= n; i++) sort(g[i].begin(), g[i].end());
		for (int m = 1; m <= n; m++)
		{
			for (int R = 1; R <= m; R++)
			{
				tot1 = g[R].size(), tot2 = g[m].size();
				dlx.reset(tot2, tot1);
				for (int i = 0; i < tot2; i++)
					for (int j = 0; j < tot1; j++)
						if ((g[m][i] | g[R][j]) == g[m][i])
							dlx.insert(i + 1, j + 1);
				dlx.Dfs(0);
				printf("%d ", dlx.num);
			}
			printf("\n");
		}
		printf("\n\n");
	}
	return 0;
}*/

int ans[10][10][10]=
{
	{
		{1}
	},
	{
		{2},
		{1, 1}
	},
	{
		{3},
		{2,3},
		{1, 1, 1}
	},
	{
		{4},
		{2, 6},
		{2, 3, 4},
		{1, 1, 1, 1}
	},
	{
		{5},
		{3, 10},
		{2, 4, 10},
		{2, 3, 4, 5},
		{1, 1, 1, 1, 1}
	},
	{
		{6},
		{3, 15},
		{2, 6, 20},
		{2, 3, 6, 15},
		{2, 3, 4, 5, 6},
		{1, 1, 1, 1, 1, 1}
	},
	{
		{7},
		{4, 21},
		{3, 7, 35},
		{2, 5, 12, 35},
		{2, 3, 5, 9, 21},
		{2, 3, 4, 5, 6, 7},
		{1, 1, 1, 1, 1, 1, 1}
	},
	{
		{8},
		{4, 28},
		{3, 11, 56},
		{2, 6, 14, 70},
		{2, 4, 8, 20, 56},
		{2, 3, 4, 7, 12, 28},
		{2, 3, 4, 5, 6, 7, 8},
		{1, 1, 1, 1, 1, 1, 1, 1}
	}
};

int n, m, R;

int main()
{
	int t, cas = 0;
	scanf("%d", &t);
	while (t--)
	{
		scanf("%d%d%d", &n, &m, &R);
		printf("Case #%d: %d\n", ++cas, ans[n - 1][m - 1][R - 1]);
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值