CF1654C Alice and the Cake- Codeforces Round #778 (Div. 1 + Div. 2, based on Technocup 2022 Final

本文介绍了Codeforces上的Problem-1654C,即Alice和蛋糕问题。题目要求通过一系列特定的蛋糕切割操作,判断是否能从初始的大块蛋糕得到给定的蛋糕重量序列。解决方案涉及逆向思维,通过合并蛋糕重量,然后模拟切割过程来验证可能性。文章提供了样例输入和输出,并解释了成功的判断条件和解题策略。
摘要由CSDN通过智能技术生成

Problem - 1654C - Codeforces

C. Alice and the Cake

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Alice has a cake, and she is going to cut it. She will perform the following operation n−1n−1 times: choose a piece of the cake (initially, the cake is all one piece) with weight w≥2w≥2 and cut it into two smaller pieces of weight ⌊w2⌋⌊w2⌋ and ⌈w2⌉⌈w2⌉ (⌊x⌋⌊x⌋ and ⌈x⌉⌈x⌉ denote floor and ceiling functions, respectively).

After cutting the cake in nn pieces, she will line up these nn pieces on a table in an arbitrary order. Let aiai be the weight of the ii-th piece in the line.

You are given the array aa. Determine whether there exists an initial weight and sequence of operations which results in aa.

Input

The first line contains a single integer tt (1≤t≤1041≤t≤104) — the number of test cases.

The first line of each test case contains a single integer nn (1≤n≤2⋅1051≤n≤2⋅105).

The second line of each test case contains nn integers a1,a2,…,ana1,a2,…,an (1≤ai≤1091≤ai≤109).

It is guaranteed that the sum of nn for all test cases does not exceed 2⋅1052⋅105.

Output

For each test case, print a single line: print YES if the array aa could have resulted from Alice's operations, otherwise print NO.

You may print each letter in any case (for example, YES, Yes, yes, yEs will all be recognized as positive answer).

Example

input

Copy

14
1
327
2
869 541
2
985214736 985214737
3
2 3 1
3
2 3 3
6
1 1 1 1 1 1
6
100 100 100 100 100 100
8
100 100 100 100 100 100 100 100
8
2 16 1 8 64 1 4 32
10
1 2 4 7 1 1 1 1 7 2
10
7 1 1 1 3 1 3 3 2 3
10
1 4 4 1 1 1 3 3 3 1
10
2 3 2 2 1 2 2 2 2 2
4
999999999 999999999 999999999 999999999

output

Copy

YES
NO
YES
YES
NO
YES
NO
YES
YES
YES
YES
NO
NO
YES

Note

In the first test case, it's possible to get the array aa by performing 00 operations on a cake with weight 327327.

In the second test case, it's not possible to get the array aa.

In the third test case, it's possible to get the array aa by performing 11 operation on a cake with weight 19704294731970429473:

  • Cut it in half, so that the weights are [985214736,985214737][985214736,985214737].

Note that the starting weight can be greater than 109109.

In the fourth test case, it's possible to get the array aa by performing 22 operations on a cake with weight 66:

  • Cut it in half, so that the weights are [3,3][3,3].
  • Cut one of the two pieces with weight 33, so that the new weights are [1,2,3][1,2,3] which is equivalent to [2,3,1][2,3,1] up to reordering.

本题逆向思维,直接拼凑是很难拼凑的,我们考虑分解。值得注意的是,偶数蛋糕分解时,一定是相同两块,奇数时,比如7,是一块3一块4,质量还是不变,故我们直接相加得到总和就是原来一块蛋糕时的质量。然后我们对其进行切割,这里我们先对小块蛋糕质量进行排序,从大到小。现在我们要进行切割,每次切割我们把切完的放进一个大根堆。如果当前取出的蛋糕是比小块蛋糕当前最大的还要大,那么说明我们必须要继续切割才能匹配成功,如果正好一样,那么我们将二者抵消,如果小于,也就是说我们无论如何也不可能再切出和小块蛋糕当前最大的一样质量的蛋糕。值得注意的是,我们判断成功的条件是,蛋糕全部被切完并且正好匹配n次(切n-1次)

#include<bits/stdc++.h>
using namespace std;

typedef long long int ll;

ll a[200000+10];

bool cmp(ll x,ll y)
{
    return x>y;

}

priority_queue<ll>q;

int main ()
{


// 首先合并蛋糕
//再进行切割,每次我们取出当前最大值,
//大根堆所放置的是我们当前切好蛋糕的最大值
//一旦这个最大值比我们数组中的最大值还要小,也就意味着我们无法再切出
//数组中存在的最大值,而我们一旦正好能够切出,直接弹出并且数组指针
//偏移即可,一旦大于当前最大,那么就必须切割了
//成功的条件为,全部切完并且数组全部用完


int t;

cin>>t;

while(t--)
{
    ll n,sum=0;

    cin>>n;

    for(int i=1;i<=n;i++)
    {
        cin>>a[i];

        sum+=a[i];

    }

    while(!q.empty())
        q.pop();


    q.push(sum);

    sort(a+1,a+1+n,cmp);
    ll left=1;


    while(!q.empty())
    {
        while(!q.empty()&&left<=n&&q.top()==a[left])
        {
            left++;
            q.pop();
        }

        if(q.empty()||left==n+1)
            break;

        if(q.top()<a[left])
            break;

        ll now=q.top();

        q.pop();

        q.push((ll)(now/2.0));

        q.push(ceil(now/2.0));

    }

    if(left==n+1&&q.empty())
        cout<<"YES"<<endl;
    else
        cout<<"NO"<<endl;




}
    return 0;

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qinsanma and Code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值