codeforces 刷题简单题题解

Posted on 2022-02-14 21:32  ZheyuHarry  阅读(507)  评论(0)    收藏  举报

Codeforces 刷题题解(简单题)

1631 AMin Max Swap

题目:You are given two arrays a and b of n positive integers each. You can apply the following operation to them any number of times:

 

Select an index i (1in) and swap ai with bi (i. e. ai becomes bi and vice versa).

Find the minimum possible value of max(a1,a2,,an)max(b1,b2,,bn) you can get after applying such operation any number of times (possibly zero).

 

Input

The input consists of multiple test cases. The first line contains a single integer t (1t100) the number of test cases. Description of the test cases follows.

 

The first line of each test case contains an integer n (1n100) the length of the arrays.

 

The second line of each test case contains n integers a1,a2,,an (1ai10000) where ai is the i-th element of the array a.

 

The third line of each test case contains n integers b1,b2,,bn (1bi10000) where bi is the i-th element of the array b.

 

Output

For each test case, print a single integer, the minimum possible value of max(a1,a2,,an)max(b1,b2,,bn) you can get after applying such operation any number of times.

 

题解:这道题我们看到可以进行无数次操作,只要我们得到的两个arraymax之积尽可能小,所以我们要想到这是一个贪心的问题,我们要做出当前看来是最优的选择。

所以我们来看这个问题,已知ab这两个数列的最大值肯定是变不了,要么在a中,要么在b中,我们要通过贪心去考虑的是使另一个数列中的max尽可能小,所以我们可以这样思考,如果要更改另一个数列的最大值,而且是往下压缩,所以另一个数列的最大值要与它对应的aibi)大,才有交换的必要,不然就越变越大,这样之后我们还要再看,如果更新后的值仍是当前数列的最大值,说明没有继续换的必要了,因为当前数列的最大值已固定,且变换的话只会变得更大,所以可以直接得出maxamaxb,不然的话,我们就要再次找到下一个的max,循环上述操作,直到退出循环。

接下来就是代码实现的问题,我们用了一个pair来存位置,在每次更新最大值后,我们sort一下数列来看最大值是否还是哪个位置上的值。然后可以根据maxamaxb进行分类。

MY code

#include<bits/stdc++.h>

 

using namespace std;

typedef pair<int,int> PII;

int main()

{

int t;

cin>>t;

while(t--){

PII arr1[105];

PII arr2[105];

int n,maxa=-1,maxb=-1;

cin>>n;

int a[105],b[105];

for(int i=0;i<n;i++) {

  scanf("%d",&a[i]);

  arr1[i].first=a[i];

  arr1[i].second=i;

  maxa=max(a[i],maxa);

}

for(int i=0;i<n;i++) {

  scanf("%d",&b[i]);

  arr2[i].first=b[i];

  arr2[i].second=i;

  maxb=max(b[i],maxb);

}

sort(arr1,arr1+n);

sort(arr2,arr2+n);

if(maxa>maxb){

for(int i=n-1;;){

int k=arr2[i].second;

if(a[k]<b[k]){

int mid=a[k];

a[k]=b[k];

b[k]=mid;

}

arr2[i].first=b[k];

sort(arr2,arr2+n);

if(b[k]==arr2[i].first) {

maxb=b[k];

break;

}

}

cout<<maxa*maxb;

}

else {

for(int i=n-1;;){

int k=arr1[i].second;

if(a[k]>b[k]){

int mid=a[k];

a[k]=b[k];

b[k]=mid;

}

arr1[i].first=a[k];

sort(arr1,arr1+n);

if(a[k]==arr1[i].first) {

maxa=a[k];

break;

}

}

cout<<maxa*maxb;

}

if(t) cout<<endl;

}

return 0;

}

 

Promotion

其实,我们不需要像上面一样一步步的考虑,我们已经固定了m1,只需最小化m2,所以我们假定m1b数列,所以遍历数列,

Ifai>biswapai,bi; 不管怎么样,我们都把能换的都换了,所以a数列再想交换,也只有变大的可能性,这就是贪心的真正意义!

所以我们可以写出以下代码:

 

Better Code

#include<bits/stdc++.h>

 

using namespace std;

 

int cal_max(vector<int> a){

int res=-1;

for(int i=0;i<a.size();i++) res=max(res,a[i]);

return res;

}

 

int main()

{

int t;

cin>>t;

while(t--){

int n,mid;

cin>>n;

vector<int> a;

vector<int> b;

for(int i=0;i<n;i++){

scanf("%d",&mid);

a.push_back(mid);

}

for(int i=0;i<n;i++){

scanf("%d",&mid);

b.push_back(mid);

}

for(int i=0;i<n;i++){

if(a[i]>b[i]) {

int middle=a[i];

a[i]=b[i];

b[i]=middle;

}

}

cout<<cal_max(a)*cal_max(b)<<endl;

}

return 0;

}

 

比较:这样一看,我们直接将代码缩短了一半,而且十分容易理解。

而且也只是On)的时间复杂度,这才是贪心,我们把每一个情况都给它考虑到了最优解。

 

 

 

1631 BFun with Even Subarrays:

 

You are given an array a of n elements. You can apply the following operation to it any number of times:

 

Select some subarray from a of even size 2k that begins at position l (1≤l≤l+2⋅k−1≤n, k≥1) and for each i between 0 and k−1 (inclusive), assign the value al+k+i to al+i.

For example, if a=[2,1,3,4,5,3], then choose l=1 and k=2, applying this operation the array will become a=[3,4,3,4,5,3].

 

Find the minimum number of operations (possibly zero) needed to make all the elements of the array equal.

 

Input

The input consists of multiple test cases. The first line contains a single integer t (1≤t≤2⋅104) — the number of test cases. Description of the test cases follows.

 

The first line of each test case contains an integer n (1≤n≤2⋅105) — the length of the array.

 

The second line of each test case consists of n integers a1,a2,…,an (1≤ai≤n) — the elements of the array a.

 

It is guaranteed that the sum of n over all test cases does not exceed 2⋅10e5.

 

Output

Print t lines, each line containing the answer to the corresponding test case — the minimum number of operations needed to make equal all the elements of the array with the given operation.

 

题解:

   首先我们把那个操作说的像人话一点:也就是说,我们在数列范围内,可以把前[k,2k]的值赋到[0,k]上,然后问我们可以最少通过几次就把整个数列变成相同的颜色。

   然后我们通过阅读这道题就可以发现,其实每次的操作都是从右往左copy,所以最后数列的所有元素都等于a[n-1],然后我们每次复制值肯定要尽可能多的复制,也就是要去看从右往左最长重复字串的元素个数,然后我们又去一个个的更改值。

  在去寻找数之前,我们要先特判一下,如果只有一个元素活着本身所有元素都已经相同,那我就直接输出0;(但是,我们其实发现根本不需要加特判,时间复杂度也不会增加,反而会使代码更简单)

  但是呢,我们如果一个个去数有多少个重复元素会超时,所以我们要用数学的方法去巧记,我们每次都是把k个值复制到前面,所以下一次就会变成2k,但是呢,其实2k之后还有可能相同的元素,所以我们要再往后数一下,但是至少我们少数了k次,循环的边界条件就是之后的那个k>=n,就已经说明我们的目的达到了。

  用代码来实现,past代表每次最长重复元素子串,然后将其赋给num,用num来调控k个值的更改,每次都对past进行double和搜索,边界条件:if(past>=n) break;

 MY Code

#include<bits/stdc++.h>

 

using namespace std;

 

int n;

 

int main()

{

int t;

cin>>t;

while(t--){

int cnt=0;

cin>>n;

        vector<int> v;

for(int i=0;i<n;i++) {

int mid;

scanf("%d",&mid);

v.push_back(mid);

}

int num=0,past=0;

for(int i=n-1;i>=0;i--){

if(v[i]==v[n-1]) num++;

else break;

}

past=num;

while(1){

int k=0;

for(int i=n-1-past;i>=0;i--){

if(v[i]==v[n-1]) past++;

else break;

}

if(past>=n) break;

num=past;

for(int i=n-1-num;i>=0;i--){

if(v[i]!=v[n-1]) k=1;

v[i]=v[n-1];

num--;

if(!num) break;

}

past*=2;

if(k) {

cnt++;

k=0;

}

}

 cout<<cnt;

   if(t) cout<<endl;

}

return 0;

}

 

比较:这道题没有比我更好的方法,因为我们肯定是要一次次地去找那个边界,然后我们这里寻找边界时是运用了double的方法,而不是真的一个个的去找,所以只要108ms,题解给出的两个算法都是200ms

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1629 A: Download More RAM:

Did you know you can download more RAM? There is a shop with n different pieces of software that increase your RAM. The i-th RAM increasing software takes ai GB of memory to run (temporarily, once the program is done running, you get the RAM back), and gives you an additional bi GB of RAM (permanently). Each software can only be used once. Your PC currently has k GB of RAM.

 

Note that you can't use a RAM-increasing software if it takes more GB of RAM to use than what you currently have.

 

Since RAM is the most important thing in the world, you wonder, what is the maximum possible amount of RAM achievable?

 

Input

The first line of the input contains a single integer t (1t100) the number of test cases. The description of test cases follows.

 

The first line of each test case contains the integers n and k (1n100, 1k1000). Then two lines follow, each containing n integers describing the arrays a and b (1ai,bi1000).

 

Output

For each test case, output a single line containing the largest amount of RAM you can achieve.

 

题解:这道题没什么好多讲的,我们把这个问题比喻成游戏中不同的副本需要不同的等级才能去打,我们等级允许的情况下,把副本打通关,获得经验值,然后去打下一个副本,如此往复,直到把当前能打的副本都打完后,仍然无法升级到下一个副本所需要的的等级条件,就可以退出,并告知我们当前的等级,所以我们只需要给副本依据等级要求升序排序,然后从前往后来一个个打副本,找到第一个打不了的副本时,就退出。

代码实现:我们只需要用一个结构体来存储所需等级,以及打完这个副本能升多少等级,再给这个重载<符号即可,然后就是遍历了。(其实我们要知道,这个只有两个的结构体,且要升序排序的,我们可以直接用pair,因为他已经自己定义了排序的方向);

 

 

MY Code

#include<bits/stdc++.h>

 

using namespace std;

 

typedef struct node{

int a;

int b;

bool operator < (const node& t) const{

  return a<t.a;

}  /*重载了<运算符,如果要降序排序,return换成>就行了*/

}node;

 

int main()

{

int t;

cin>>t;

while(t--){

int n,k;

node a[105];

cin>>n>>k;

for(int i=0;i<n;i++){

scanf("%d",&a[i].a);

}

for(int i=0;i<n;i++){

scanf("%d",&a[i].b);

}

sort(a,a+n);

int m=0;

while(k>=a[m].a&&m<n){

k+=a[m].b;

m++;

}

cout<<k;

if(t) cout<<endl;

}

return 0;

}

 

 

1629 BGCD Arrays

Consider the array a composed of all the integers in the range [l,r]. For example, if l=3 and r=7, then a=[3,4,5,6,7].

(这里的array是根据lr得到的)

Given l, r, and k, is it possible for gcd(a) to be greater than 1 after doing the following operation at most k times?

 

Choose 2 numbers from a.

Permanently remove one occurrence of each of them from the array.

Insert their product back into a.

gcd(b) denotes the greatest common divisor (GCD) of the integers in b.

 

Input

The first line of the input contains a single integer t (1t105) the number of test cases. The description of test cases follows.

 

The input for each test case consists of a single line containing 3 non-negative integers l, r, and k (1lr109,0krl).

 

Output

For each test case, print "YES" if it is possible to have the GCD of the corresponding array greater than 1 by performing at most k operations, and "NO" otherwise (case insensitive).

 

题解:

  这道题其实是数论的范围,因为其本身作为编程来讲,在coding上并没有太大的难度,主要是为什么要这么样去思考,值得思量。

  首先我们要进行特判,如果l==r&&l==1,那么就等于1,输出“NO”,else ifl==r),那么就为大于一的整数,恰好满足条件,直接输出“YES”;

  然后我们对其他情况进行说明,首先我们要知道我们要先以hh>1)为公因子,然后找到以h为因子的数,使他和不含h的数字进行操作,所以只要不含h的数字个数<=最大允许的操作数,我们就说是可以达到的,输出“YES”。

我们还可以发现,在lrk已经固定的情况下,这个h是我们自己定义的,我们为了满足题意,自然要尽可能的使h更加普遍的存在于数列的元素中,那么我们自然就可以发现,2是大于1的最常见的公因子,所以这道题就变成了找奇数有几个的问题。而且这里的数列是根据lr唯一确定的,所以可以运用结论:

Oddnum = (r-l+1)  -  (  (r)/2  -  (l-1)/2  )

代码实现:这道题没有实现上的困难,因为数值特别小,我们就是直接暴力求解即可。

 

MY Code

#include<bits/stdc++.h>

 

using namespace std;

 

int main()

{

int t;

cin>>t;

while(t--){

int l,r,k;

cin>>l>>r>>k;

if(l==r &&l==1) cout<<"NO";

else if(l==r) cout<<"YES";

else{

int num=(r-l+1)-((r)/2-(l-1)/2);

if(num<=k) cout<<"YES";

else cout<<"NO";

}

if(t) cout<<endl;

}

return 0;

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1632 A: ABC

题目:

Recently, the students of School 179 have developed a unique algorithm, which takes in a binary string s as input. However, they soon found out that if some substring t of s is a palindrome of length greater than 1, the algorithm will work incorrectly. Can the students somehow reorder the characters of s so that the algorithm will work correctly on the string?

 

A binary string is a string where each character is either 0 or 1.

 

A string a is a substring of a string b if a can be obtained from b by deletion of several (possibly, zero or all) characters from the beginning and several (possibly, zero or all) characters from the end.

 

A palindrome is a string that reads the same backwards as forwards.

 

Input

Each test contains multiple test cases. The first line contains the number of test cases t (1≤t≤100). Description of the test cases follows.

 

The first line of each test case contains a single integer n (1≤n≤100) — the length of the string s.

 

The second line of each test case contains the string s of length n consisting only of the characters 0 and 1.

 

Output

For each test case, print YES (case-insensitive) if it is possible to reorder the characters of s so that there are no substrings that are a palindrome of length greater than 1, or NO (case-insensitive) otherwise.

 

 

题解:这道题就是说我们不能在一个序列中出现回文串,但是我们已知这是一个binary string ,只有01,我们可以发现,不管怎么样,不能让0011出现,所以肯定是101或者0101这样的序列(10交替出现),但是这样我们会发现,当序列长度大于2时,一定会有长度大于一的回文串。所以我们可以直接对输入的序列长度进行判断,当n>=3时,肯定输出NOn==2时,如果两个字符相同,也输出NO,其他情况都输出YES。非常简单哦,动动脑子就好了!

MY Code:

#include<bits/stdc++.h>

 

using namespace std;

int main()

{

int t;

cin>>t;

while(t--){

int n;

cin>>n;

string str;

cin>>str;

if(n<=2){

if(str[0]!=str[1]) cout<<"YES";

else cout<<"NO";

}

else cout<<"NO";

if(t) cout<<endl;

}

return 0;

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1632B:Roof Construction

题目:

It has finally been decided to build a roof over the football field in School 179. Its construction will require placing nn consecutive vertical pillars. Furthermore, the headmaster wants the heights of all the pillars to form a permutation pp of integers from 00 to n−1n−1, where pipi is the height of the ii-th pillar from the left (1≤i≤n)(1≤i≤n).

As the chief, you know that the cost of construction of consecutive pillars is equal to the maximum value of the bitwise XOR of heights of all pairs of adjacent pillars. In other words, the cost of construction is equal to max1≤in−1pipi+1max1≤i≤n−1pi⊕pi+1, where  denotes the bitwise XOR operation.

Find any sequence of pillar heights pp of length nn with the smallest construction cost.

In this problem, a permutation is an array consisting of nn distinct integers from 00 to n−1n−1 in arbitrary order. For example, [2,3,1,0,4][2,3,1,0,4] is a permutation, but [1,0,1][1,0,1] is not a permutation (11 appears twice in the array) and [1,0,3][1,0,3] is also not a permutation (n=3n=3, but 33 is in the array).

Input

Each test contains multiple test cases. The first line contains the number of test cases tt (1≤t≤1041≤t≤104). Description of the test cases follows.

The only line for each test case contains a single integer nn (2≤n≤2⋅1052≤n≤2⋅105) — the number of pillars for the construction of the roof.

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

Output

For each test case print nn integers p1p1, p2p2, ……, pnpn — the sequence of pillar heights with the smallest construction cost.

If there are multiple answers, print any of them.

 

 

 

题解:

我们已知这是一个连续的[0,n-1]的数字序列,我们要知道两个相近元素的按位异或的最大值,因为我们可以看到这里的N<=210e5 ,我们肯定不可能一个个的去搜索,所以我们要去发现这个数的二进制表示的一些特点;

因为是二进制序列,我们可以知道,这是跟2^n相关的,因为是连续的序列,对于最大的那个2^k,其二进制序列为1000……,其他则是会有01011……这种,就是说,按位异或,至少会有2^k,我们为了使之不要变得更大,所以令2^k左边是0,比2^k大的就在其右边,小的在0左边,这样的话,其实无论其顺序如何,一定不会超过2^k

MY Code

#include<bits/stdc++.h>

 

using namespace std;

 

int main()

{

int t;

cin>>t;

while(t--){

int n;

cin>>n;

int k;

for(k=0;;k++){

if((1<<k)>=n) {

k--;

break;

}

}

for(int i=1;i<(1<<k);i++) printf("%d ",i);

printf("0 ");

if((1<<k)==n-1) printf("%d",(1<<k));

else {

for(int i=(1<<k);i<n;i++) {

printf("%d",i);

if(i!=n-1) printf(" ");

}

}

if(t) cout<<endl;

}

return 0;

}

 1632 C:Strange Test

题目:Igor is in 11th grade. Tomorrow he will have to write an informatics test by the strictest teacher in the school, Pavel Denisovich.

 

Igor knows how the test will be conducted: first of all, the teacher will give each student two positive integers a and b (a<b). After that, the student can apply any of the following operations any number of times:

 

a:=a+1 (increase a by 1),

b:=b+1 (increase b by 1),

a:=a | b (replace a with the bitwise OR of a and b).

To get full marks on the test, the student has to tell the teacher the minimum required number of operations to make a and b equal.

 

Igor already knows which numbers the teacher will give him. Help him figure out what is the minimum number of operations needed to make a equal to b.

 

Input

Each test contains multiple test cases. The first line contains the number of test cases t (1t104). Description of the test cases follows.

 

The only line for each test case contains two integers a and b (1a<b106).

 

It is guaranteed that the sum of b over all test cases does not exceed 106.

 

Output

For each test case print one integer the minimum required number of operations to make a and b equal.

 

题解:

  因为我们可以了解到我们最多使用第三种operation一次,使用一次之后(b<=a),就只能去执行第二种operation了。所以我们要找到操作第三种operationab的变形a1b1.所以最后的ans=a1 - a - b + (a1 | b1) + 1

  其中a1-a是第一种操作的次数,(a1|b1-b是执行第三次操作后第二次操作所需要执行的次数,+1是第三次操作。

所以问题就转化成了找到那个a1b1的问题了,我们可以根据二进制位来看,我么从最高位到最低位列举a1a<=a

1<b,满足一下规则:

  If current bit of ais 0 and b is 1, set the current bit of bto 1.

If current bit of ais 0 and b is 0, set the current bit of bto 0.

If current bit of ais 1 and b is 1, set the current bit of bto 1.

If current bit of ais 1 and b is 0, set the current bit of bto 1 and stop.

 

因为我们列举a1ab都是固定的,所以我们其实要最小化(a1|b1),因为a1已经固定了,所以我们要让b1越小越好,而如上规则产生的b1是最小的满足条件的大于b的数。(换句话说,我们要让二进制位中的1越少越好)。

因为a1是在[a,b)的范围中去列举的,是10^5数量级,二进制位最多21位,<<10^8的条件,所以我们可以直接暴力列举a1,去固定b1.

MY Code:

#include<bits/stdc++.h>

using namespace std;

 

 

int main() {

    int t;

    cin >> t;

    while(t--) {

        int a, b;

        cin >> a >> b;

        int ans = b - a;

        for(int a1 = a; a1 < b; a1++) {

            int b1 = 0;

            for(int i = 21; i >= 0; i--) {//这里就是对每一个不同的位数进行操作,还是挺好理解,这里是logb

                if((b >> i) & 1) {

                    b1 ^= (1 << i);

                } else {

                    if((a1 >> i) & 1) {

                        b1 ^= (1 << i);

                        break;

                    }

                }

            }

            ans = min(ans, a1 - a - b + (a1 | b1) + 1);

        }

        cout << ans << '\n';

    }

}

  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1633C. Kill the Monster

 

题目:

Monocarp is playing a computer game. In this game, his character fights different monsters.

 

A fight between a character and a monster goes as follows. Suppose the character initially has health hC and attack dC; the monster initially has health hM and attack dM. The fight consists of several steps:

(回合制)

the character attacks the monster, decreasing the monster's health by dC;

the monster attacks the character, decreasing the character's health by dM;

the character attacks the monster, decreasing the monster's health by dC;

the monster attacks the character, decreasing the character's health by dM;

and so on, until the end of the fight.

The fight ends when someone's health becomes non-positive (i. e. 0 or less). If the monster's health becomes non-positive, the character wins, otherwise the monster wins.

 

Monocarp's character currently has health equal to hC and attack equal to dC. He wants to slay a monster with health equal to hM and attack equal to dM. Before the fight, Monocarp can spend up to k coins to upgrade his character's weapon and/or armor; each upgrade costs exactly one coin, each weapon upgrade increases the character's attack by w, and each armor upgrade increases the character's health by a.

 

Can Monocarp's character slay the monster if Monocarp spends coins on upgrades optimally?

 

Input

The first line contains one integer t (1≤t≤5⋅10e4) — the number of test cases. Each test case consists of three lines:

 

The first line contains two integers hC and dC (1≤hC≤10e15; 1≤dC≤10e9) — the character's health and attack;

 

The second line contains two integers hM and dM (1≤hM≤1015; 1≤dM≤109) — the monster's health and attack;

 

The third line contains three integers k, w and a (0≤k≤2⋅10e5; 0≤w≤10e4; 0≤a≤10e10) — the maximum number of coins that Monocarp can spend, the amount added to the character's attack with each weapon upgrade, and the amount added to the character's health with each armor upgrade, respectively.

 

The sum of k over all test cases does not exceed 2⋅10e5.

 

Output

For each test case, print YES if it is possible to slay the monster by optimally choosing the upgrades. Otherwise, print NO.

 

题解:

读题后先浓缩一下大意:勇者能否通过给装备升级在回合制的比赛中打败恶龙。看起来很高大上,但是这道题给的数据小,是个OK)的时间复杂度,好家伙,我直接暴力求解。我一一列举k全部用完的情况,然后分别看勇者和恶龙对应能坚持的轮数,ifround 勇者)>=round 恶龙)退出循环,coutYES”,反之亦然。

 

启示:这道题其实提醒我们这种看起来有些麻烦的题,直接枚举就够了!

 

MY Code

#include<bits/stdc++.h>

 

using namespace std;

typedef long long LL;

 

int main()

{

int t;

cin>>t;

while(t--){

LL hc,dc,hm,dm,k,w,a;

cin>>hc>>dc;

cin>>hm>>dm;

cin>>k>>w>>a;

int i=0;

  for( i=0;i<=k;i++){

  LL midhc=hc+i*a;

  LL middc=dc+(k-i)*w;

  LL col1=midhc/dm;

  if(midhc%dm!=0) col1++;

  LL col2=hm/middc;

  if(hm%middc) col2++;

  if(col1>=col2) break;

  }

  if(i==k+1) cout<<"NO";

  else cout<<"YES";

if(t) cout<<endl;

}

return 0;

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Round 770 div 2: B. Fortune Telling

题目:

Your friends Alice and Bob practice fortune telling.

 

Fortune telling is performed as follows. There is a well-known array a of n non-negative integers indexed from 1 to n. The tellee starts with some non-negative number d and performs one of the two operations for each i=1,2,…,n, in the increasing order of i. The possible operations are:

 

replace their current number d with d+ai

replace their current number d with d⊕ai (hereinafter ⊕ denotes the bitwise XOR operation)

Notice that the chosen operation may be different for different i and for different tellees.

 

One time, Alice decided to start with d=x and Bob started with d=x+3. Each of them performed fortune telling and got a particular number in the end. Notice that the friends chose operations independently of each other, that is, they could apply different operations for the same i.

 

You learnt that either Alice or Bob ended up with number y in the end, but you don't know whose of the two it was. Given the numbers Alice and Bob started with and y, find out who (Alice or Bob) could get the number y after performing the operations. It is guaranteed that on the jury tests, exactly one of your friends could have actually gotten that number.

 

Hacks

 

You cannot make hacks in this problem.

 

Input

On the first line of the input, you are given one number t (1≤t≤104) — the number of test cases. The following 2⋅t lines contain test cases.

 

The first line of each test case contains three numbers n, x, y (1≤n≤105, 0≤x≤109, 0≤y≤1015) — the length of array a, Alice's initial number (Bob's initial number is therefore x+3), and the number that one of the two friends got in the end.

 

The second line of each test case contains n numbers — the array a (0≤ai≤109).

 

It is guaranteed that the sum of n over all test cases does not exceed 105.

 

Output

For each test case, print the name of the friend who could get the number y: "Alice" or "Bob".

 

题解:

  

我们发现数字是由10^5的量级,我们如果使用BFS去模拟操作,无疑会出现Memory Limit Exceeded ,所以我们这里不是很耿直的去模拟操作,而是我们要善于发现数字之间的关系,这是一道类似于脑筋急转弯的题。

我们先来探究一下+和⊕之间的关系,当我们只看这两个数的二进制的末尾(也就是去关注它的奇偶性),我们会发现无论是加法还是按位异或其奇偶性不变.

1+1==0  ;      1^1==0;

1+0==1  ;      1^0==1;

0+1==1  ;      0^1==1;

0+0==0  ;      0^0==0;

 

而且我们还发现AlicexBobx+3,两者奇偶性不同,所以我们知道无论采取如何的操作,xx+3最后对应的奇偶性是确定的,所以我们用xarray中的所有数字都加上去,观察其奇偶性是否与y一样,若一样,则输出Alice,不然输出Bob

 

这道题没有什么代码上的难点,我们得到的启示就是加法和按位异或奇偶性不变。

 

MY Code

#include<bits/stdc++.h>

 

using namespace std;

typedef long long LL;

 

int main()

{

int t;

cin>>t;

while(t--){

LL n,x,y;

cin>>n>>x>>y;

for(LL i=0;i<n;i++){

LL mid;

cin>>mid;

x+=mid;

}

if(x%2==y%2) cout<<"Alice"<<endl;

else cout<<"Bob"<<endl;

}

return 0;

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Edu122 div2 1633D. Make Them Equal

 

题目:

You have an array of integers aa of size nn. Initially, all elements of the array are equal to 11. You can perform the following operation: choose two integers ii (1≤i≤n1≤i≤n) and xx (x>0x>0), and then increase the value of aiai by ⌊aix⌋⌊aix⌋ (i.e. S

After performing all operations, you will receive cici coins for all such ii that ai=biai=bi.

Your task is to determine the maximum number of coins that you can receive by performing no more than kk operations.

Input

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

The first line of each test case contains two integers nn and kk (1≤n≤103;0≤k≤1061≤n≤103;0≤k≤106) — the size of the array and the maximum number of operations, respectively.

The second line contains nn integers b1,b2,…,bnb1,b2,…,bn (1≤bi≤1031≤bi≤103).

The third line contains nn integers c1,c2,…,cnc1,c2,…,cn (1≤ci≤1061≤ci≤106).

The sum of nn over all test cases does not exceed 103103.

Output

For each test case, print one integer — the maximum number of coins that you can get by performing no more than kk operations.

 

题解:

因为我们一开始自己有一个序列a全是1,我们其实就是通过操作使a1变成b中的各个数字,因为我们要让a中尽可能多的数变成b中的数,所以我们肯定要让1变到这个数的时候花费的次数最少,所以我们这里要用一次动态规划。

  然后我们可以知道因为b[i]<=1000,最多经过12次变换,我们假设b中所有的数都要经过12次变换,那么最多有12n次变换,我们定义一个sum存储把a中的1统统变成b中的数所花的次数,然后

K=min12nsum);这样就把k10^6量级变成了10^4量级,这样我们就可以用Onk)的时间复杂度解决这个问题了。

  因为这道题我们不能简单的求取它的“单价”(花费1次变化所获得的coins),因为有可能还会有剩余的,比如3+21的效率就不如一个6的,所以我们要把每一种情况都考虑到!

   所以我们还要进行一次动态规划,我们创建一个dp数组,其中的下标表示着结束时进行操作的次数,所存储的值意味着操作这么多次数时,最多能产生多少收益。所以我们在这里会套两层循环,第一层遍历b数组,第二层循环0~k-d[b[i]],也就是说当我想要花费次数把1变成这个b[i]时,那么dp[j+d[b[i]] ]=max(dp[j+d[b[i]] ],dp[j]+c[i] );

  非常有趣,两次动态规划!

My Code

#include <bits/stdc++.h>

 

using namespace std;

 

const int N = 1001;

 

int main() {

  vector<int> d(N, N);

  d[1] = 0;

  for (int i = 1; i < N; ++i) {

    for (int x = 1; x <= i; ++x) {

      int j = i + i / x;

      if (j < N) d[j] = min(d[j], d[i] + 1);

    }

  }

  

  int t;

  cin >> t;

  while (t--) {

    int n, k;

    cin >> n >> k;

    vector<int> b(n), c(n);

    for (int &x : b) cin >> x;

    for (int &x : c) cin >> x;

    int sum = 0;

    for (int x : b) sum += d[x];

    k = min(k, sum);

    vector<int> dp(k + 1, 0);

    for (int i = 0; i < n; ++i) {

      for (int j = k - d[b[i]]; j >= 0; j--) {

        dp[j + d[b[i]]] = max(dp[j + d[b[i]]], dp[j] + c[i]);

      }

    }

    cout << *max_element(dp.begin(), dp.end()) << '\n';

  }

}