J: JoJo’s Bizarre Adventure
Time Limit: 1000 MS Memory Limit: 1048576 KB
Description
Dio and JoJo are playing a game.
At the beginning, JoJo writes down nn non-negative integers a1;a2;...;ana1;a2;...;an(0=a1≤a2≤⋅⋅⋅≤an0=a1≤a2≤···≤an) on a sheet of paper and a1=0a1=0 is guaranteed. Then, he makes a multiset Smulti={ai+aj|1≤i<j≤n}Smulti={ai+aj|1≤i<j≤n}, and tells the numbers to Dio within Smulti in non-decreasing order one after another.
As for Dio, he wins the game if and only if he can determine the original nn numbers aiai(1≤i≤n1≤i≤n) after receiving some of the numbers in Smulti given by JoJo.
If Dio can't win the game as soon as possible, he won't be a human anymore. So can you help him determine the earliest time to win?
Input
The first line contains a integer TT representing the number of test cases.In each test case, the first line contains one integer nn.The second line contains n×(n−1)2n×(n−1)2 integers, the i−thi−th integer sisi represents the i−thi−th element in SmultiSmulti.It is guaranteed that the numbers in SmultiSmulti are generated by some nn non-negative integers a1;...;ana1;...;an
and given in non-decreasing order
1≤T≤10 1≤T≤101≤n≤5001≤n≤500 0≤si≤1090≤si≤109 0<∑n≤1000
Output
Sample Input
2
4
1 2 3 3 4 5
4
1 2 2 3 3 4
Sample Output
4
3
现场以为数学题,回来发现是道数据结构题。。
题意:
有k组数据,先输入一个n表示有n个数,再输入n(n-1)个数,这些数是an中两个数(这两个数不同)的和,从小到大输入,且a0=0。问:最少输入到第几个数,可以完全写出an中每一个数的值。
前两组数据肯定是 a0+a1,a0+a2,这样我们就知道了a1,a2了。
这题的关键点就是一个结论:当新出现的和 无法用已知的所有数字表示时,这个和肯定为0+a的形式,即:这个数就是一个新的a
然后map一顿操作就ok,注意这里不要用set,遇到重的没法表示,这里的sum相当于一个计数set。
/*暴力找,强力剪枝*/
#include <iostream>
#include <set>
#include <map>
using namespace std;
#define ll long long
map<ll,ll>m;
map<ll,ll>sum;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t;
cin>>t;
while(t--)
{
m.clear();
sum.clear();
ll a;
bool find_answer=0;
int tot=0;
int n;
cin>>n;
int S=n*(n-1)/2;
int ans=S;
for(int i=1;i<=S;i++)
{
cin>>a;
bool flag=0;//flag为1表示这个数可以用已经知道的a表示
if(find_answer==0&&sum.find(a)!=sum.end()&&sum.find(a)->second!=0)//这个数可以用已知的数表示
{
sum.find(a)->second--;
flag=1;
}
else if(flag==0&&find_answer==0)//没找到,新加一个
{
m[tot]=a;
if(m.size()>1)
{
for(int j=0;j<m.size()-1;j++)//将新加进来的数和原来的数的新的组合添加进sum里
{
sum[a+m[j]]++;
}
}
tot++;
if(m.size()==n-1)
{
ans=i;
find_answer=1;
}
}
}
cout<<ans<<endl;
}
return 0;
}