第十届四川省省赛 J: JoJo’s Bizarre Adventure

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=a1a2an0=a1≤a2≤···≤an) on a sheet of paper and a1=0a1=0 is guaranteed. Then, he makes a multiset Smulti={ai+aj|1i<jn}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(1in1≤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×(n1)2n×(n−1)2 integers, the ithi−th integer sisi represents the ithi−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

1T10 1≤T≤10
1n5001≤n≤500 0si1090≤si≤109 0<n1000


Output

For each test case, output a number xx in one line indicating that after receiving xx sums, Dio can determine the original nn numbers.

Sample Input

2

4

1 2 3 3 4 5

4

1 2 2 3 3 4

Sample Output

4

3


丢人现场。。死于jojo。。

现场以为数学题,回来发现是道数据结构题。。


题意:

有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;
}



猜你喜欢

转载自blog.csdn.net/neuq_zsmj/article/details/80697893
今日推荐