您的位置:首页 > 大数据 > 人工智能

2017 Multi-University Training Contest - Team 5 1008 Rikka with Subset

2017-08-08 20:41 633 查看

Rikka with Subset

[align=center]Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 568    Accepted Submission(s): 241
[/align]

[align=left]Problem Description[/align]

As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Rikka some math tasks to practice. There is one of them:

Yuta has n
positive A1−An
and their sum is m.
Then for each subset S
of A,
Yuta calculates the sum of S.

Now, Yuta has got 2n
numbers between [0,m].
For each i∈[0,m],
he counts the number of is
he got as Bi.

Yuta shows Rikka the array Bi
and he wants Rikka to restore A1−An.

It is too difficult for Rikka. Can you help her?  
 

[align=left]Input[/align]

The first line contains a numbert(1≤t≤70),
the number of the testcases.

For each testcase, the first line contains two numbers
n,m(1≤n≤50,1≤m≤104).

The second line contains m+1
numbers B0−Bm(0≤Bi≤2n).
 

[align=left]Output[/align]

For each testcase, print a single line withn
numbers A1−An.

It is guaranteed that there exists at least one solution. And if there are different solutions, print the lexicographic minimum one.
 

[align=left]Sample Input[/align]

2
2 3
1 1 1 1
3 3
1 3 3 1

 

[align=left]Sample Output[/align]

1 2
1 1 1
Hint
In the first sample, $A$ is $[1,2]$. $A$ has four subsets $[],[1],[2],[1,2]$ and the sums of each subset are $0,1,2,3$. So $B=[1,1,1,1]$

 
官方题解:
大致的思想就是反过来的背包。
如果 Bi是B数组中除了B0以外第一个值不为0的位置,那么显然i就是A中的最小数

现在需要求出删掉 i后的B数组,过程大概是反向的背包,即从小到大让Bj−=Bj−i

时间复杂度 O(nm)

队友写的,我躺了
#include<bits/stdc++.h>
using namespace std;

#define mem(a,x) memset(a,x,sizeof a)
#define rep(i,n) for (int i=0;i<n;i++)
#define lp(i,l,r) for (int i=l;i<=r;i++)
#define rlp(i,r,l) for (int i=r;i>=l;i--)
#define T_T int _;scanf("%d",&_);for (int test=1;test<=_;test++)
typedef long long ll;
typedef double db;
const int MAXN = 10 * 1e5 + 500;

const int CN = 100;
long long c[CN][CN] = {};
void cinit()
{
for (int i = 0; i < CN; i++)
{
c[i][0] = c[i][i] = 1;
for (int j = 1; j < i; j++)
{
c[i][j] = c[i - 1][j] + c[i - 1][j - 1];
}
}
}
ll B[MAXN];
ll dp[MAXN];
ll num[100], val[100];
int main()
{
cinit();
std::ios::sync_with_stdio(false);

int T;
cin >> T;
while (T--)
{
int n, m;
cin >> n >> m;
rep(i, m + 1) cin >> B[i];

int cnt = 0;
ll sum = 0, sumnum = 0;
mem(dp, 0);
dp[0] = 1;
lp(i, 1, m - 1)
{
ll nums = B[i] - dp[i];
if (nums > 0)
{
num[++cnt] = nums;
val[cnt] = i;
sum += nums * i;
sumnum += nums;
if (sumnum >= n)
{
break;
}
rlp(j, m, i)
{
lp(k, 1, j / i)
{
if (j - k * i > sum)
{
break;
}
dp[j] += dp[j - k * i] * c[nums][k];
}
}
}
}
lp(i, 1, cnt)
{
rep(j, num[i])
{
cout << val[i];
if (j < num[i] - 1 || i < cnt)
{
cout << " ";
}
}
}
cout << endl;
}
}
/*
1
5 12
1 2 2 3  3 3 3 4 3 3 3 2 2 1
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm hdu 多校 dp
相关文章推荐