2020 CDUT寒假集训第一场
Posted heizesi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2020 CDUT寒假集训第一场相关的知识,希望对你有一定的参考价值。
目录
2020 CDUT寒假集训第一场
A - Vasya and Golden Ticket
Recently Vasya found a golden ticket — a sequence which consists of n digits a1a2…*a**n*. Vasya considers a ticket to be lucky if it can be divided into two or more non-intersecting segments with equal sums. For example, ticket 350178 is lucky since it can be divided into three segments 350, 17 and 8: 3+5+0=1+7=8. Note that each digit of sequence should belong to exactly one segment.
Help Vasya! Tell him if the golden ticket he found is lucky or not.
Input
The first line contains one integer n (2≤n≤100) — the number of digits in the ticket.
The second line contains n digits a1a2…*a**n* (0≤*a**i*≤9) — the golden ticket. Digits are printed without spaces.
Output
If the golden ticket is lucky then print "YES", otherwise print "NO" (both case insensitive).
思路:一看n只有100,别多想,暴力搜索。枚举可能出现的值,以此为基础按递归的方式尝试分出下一个可能的段,直到将整个数列划分完。
(最开始搞了个乱七八糟的剪枝,结果剪出bug了。。。)
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
int nums[105];
int sum[105];
int n;
bool dfs(int idx,int segsum)
{
if(idx==n+1)
{
return true;
}
for(int i=idx;i<=n;i++)
{
if((sum[i]-sum[idx-1])==segsum)
{
if(dfs(i+1,segsum))
{
return true;
}
}
else if((sum[i]-sum[idx-1])>segsum)
{
return false;
}
}
return false;
}
int main()
{
char tmp;
scanf("%d",&n);
getchar();
for(int i=1;i<=n;i++)
{
tmp=getchar();
nums[i]=tmp-'0';
sum[i]+=nums[i]+sum[i-1];
}
if(sum[n]==0)
{
cout<<"YES"<<endl;
return 0;
}
bool flag=0;
for(int i=1;i<n;i++)
{
if(dfs(i+1,sum[i]))
{
flag=1;
break;
}
}
if(flag)
{
cout<<"YES"<<endl;
}
else
{
cout<<"NO"<<endl;
}
return 0;
}
B - Slime
There are n slimes in a row. Each slime has an integer value (possibly negative or zero) associated with it.
Any slime can eat its adjacent slime (the closest slime to its left or to its right, assuming that this slime exists).
When a slime with a value x eats a slime with a value y, the eaten slime disappears, and the value of the remaining slime changes to x?y.
The slimes will eat each other until there is only one slime left.
Find the maximum possible value of the last slime.
Input
The first line of the input contains an integer n (1≤n≤500000) denoting the number of slimes.
The next line contains n integers *a**i* (?109≤ai≤109), where ai is the value of i-th slime.
Output
Print an only integer — the maximum possible value of the last slime.
思路:数学题,首先可以想到的是因为操作是减法操作,那么正数和负数之间运算可以使绝对值相加,而两者之间运算顺序可以改变结果的正负,那么我们可以想到的是尽量使正数和负数运算,这样使结果最后为绝对值相加。但如果全是正数或全是负数,就需要将其中一个数转换成相反的数,贪心的想选择最大的减去最小的,这样绝对值得损失才最小。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
int maxnum=-0x3f3f3f3f;
int minnum=0x3f3f3f3f;
int num[500005];
int main()
{
int n;
scanf("%d",&n);
bool flag1=0;
bool flag2=0;
long long sum=0;
long long ans=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&num[i]);
sum+=abs(num[i]);
if(num[i]<0)
{
flag1=true;
maxnum=max(maxnum,num[i]);
}
else
{
flag2=true;
minnum=min(minnum,num[i]);
}
}
if(flag1 && flag2)
{
ans=sum;
}
else if(!flag1)
{
ans=sum-minnum*2;
}
else if(!flag2)
{
ans=sum+maxnum*2;
}
if(n==1)
{
ans=num[1];
}
cout<<ans<<endl;
return 0;
}
C - Weather
Scientists say a lot about the problems of global warming and cooling of the Earth. Indeed, such natural phenomena strongly influence all life on our planet.
Our hero Vasya is quite concerned about the problems. He decided to try a little experiment and observe how outside daily temperature changes. He hung out a thermometer on the balcony every morning and recorded the temperature. He had been measuring the temperature for the last n days. Thus, he got a sequence of numbers t1,?t2,?...,?*t**n, where the i-th number is the temperature on the i*-th day.
Vasya analyzed the temperature statistics in other cities, and came to the conclusion that the city has no environmental problems, if first the temperature outside is negative for some non-zero number of days, and then the temperature is positive for some non-zero number of days. More formally, there must be a positive integer k (1?≤?k?≤?n?-?1) such that t1?<?0,?t2?<?0,?...,?tk?<?0 and tk?+?1?>?0,?tk?+?2?>?0,?...,?tn?>?0. In particular, the temperature should never be zero. If this condition is not met, Vasya decides that his city has environmental problems, and gets upset.
You do not want to upset Vasya. Therefore, you want to select multiple values of temperature and modify them to satisfy Vasya‘s condition. You need to know what the least number of temperature values needs to be changed for that.
Input
The first line contains a single integer n (2?≤?n?≤?105) — the number of days for which Vasya has been measuring the temperature.
The second line contains a sequence of n integers t1,?t2,?...,?*t**n* (|ti|?≤?109) — the sequence of temperature values. Numbers ti are separated by single spaces.
Output
Print a single integer — the answer to the given task.
思路:反正无论是什么数字修改都只算作一次,那么可以按照前缀和的思路记录第i个数字前有多少个数字大于0,同理反向记录有多少个数字小于0,最后线性的扫一遍记录最小值就可以了。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
int num[100005];
int fr[100005];
int ba[100005];
int main()
{
int n;
int ans;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&num[i]);
}
for(int i=1;i<=n;i++)
{
if(num[i]>=0)
{
fr[i]+=1;
}
fr[i]+=fr[i-1];
}
for(int i=n;i>=1;i--)
{
if(num[i]<=0)
{
ba[i]+=1;
}
ba[i]+=ba[i+1];
}
ans=n;
for(int i=2;i<=n;i++)
{
ans=min(ans,fr[i-1]+ba[i]);
}
cout<<ans<<endl;
return 0;
}
D - Vasya and Arrays
Vasya has two arrays A and B of lengths n and m, respectively.
He can perform the following operation arbitrary number of times (possibly zero): he takes some consecutive subsegment of the array and replaces it with a single element, equal to the sum of all elements on this subsegment. For example, from the array [1,10,100,1000,10000] Vasya can obtain array [1,1110,10000], and from array [1,2,3] Vasya can obtain array [6].
Two arrays A and B are considered equal if and only if they have the same length and for each valid i Ai=Bi.
Vasya wants to perform some of these operations on array A, some on array B, in such a way that arrays A and B become equal. Moreover, the lengths of the resulting arrays should be maximal possible.
Help Vasya to determine the maximum length of the arrays that he can achieve or output that it is impossible to make arrays A and B equal.
Input
The first line contains a single integer n (1≤n≤3?105) — the length of the first array.
The second line contains n integers a1,a2,?,*a**n* (1≤*a**i≤109) — elements of the array A*.
The third line contains a single integer m (1≤m≤3?105) — the length of the second array.
The fourth line contains m integers b1,b2,?,*b**m* (1≤*b**i≤109) - elements of the array B*.
Output
Print a single integer — the maximum length of the resulting arrays after some operations were performed on arrays A and B in such a way that they became equal.
If there is no way to make array equal, print "-1".
思路:因为要求两个序列是严格相等,所以可以一个一个看,按照贪心的思想尽量使等位的数相同,可以考虑用双指针定位次序
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
long long num1[300005];
long long num2[300005];
int main()
{
int n1,n2;
int sum1,sum2;
sum1=sum2=0;
scanf("%d",&n1);
for(int i=1;i<=n1;i++)
{
scanf("%lld",&num1[i]);
sum1+=num1[i];
}
scanf("%d",&n2);
for(int i=1;i<=n2;i++)
{
scanf("%lld",&num2[i]);
sum2+=num2[i];
}
int ans=0;
long long segval1=num1[1];
long long segval2=num2[1];
int idx1=1;
int idx2=1;
while(idx1!=n1+1 && idx2!=n2+1)
{
if(segval1==segval2 && segval1!=0)
{
ans++;
segval1=segval2=0;
}
if(segval1<segval2)
{
segval1+=num1[idx1+1];
idx1+=1;
}
else
{
segval2+=num2[idx2+1];
idx2+=1;
}
}
if(segval1 || segval2)
{
ans=-1;
}
if(sum1!=sum2)
{
ans=-1;
}
cout<<ans<<endl;
return 0;
}
E - Multiplicity
You are given an integer array a1,a2,…,*a**n*.
The array b is called to be a subsequence of a if it is possible to remove some elements from a to get b.
Array b1,b2,…,*b**k* is called to be good if it is not empty and for every i (1≤i≤k) *b**i* is divisible by i.
Find the number of good subsequences in a modulo 109+7.
Two subsequences are considered different if index sets of numbers included in them are different.
That is, the values of the elements do not matter in the comparison of subsequences. In particular, the array a has exactly 2n?1 different subsequences (excluding an empty subsequence).
Input
The first line contains an integer n (1≤n≤100000) — the length of the array a.
The next line contains integers a1,a2,…,*a**n* (1≤*a**i*≤106).
Output
Print exactly one integer — the number of good subsequences taken modulo 109+7.
思路:头痛,对dp+数论苦手太不友好了。先用筛法求出每个因数,再dp,记f(i,j)前i个数中长度为j的方案数,可以看出f(i,j)=f(i-1,j)+f(i-1,j-1)(ai是j的倍数)。因为只与i-1有关,可以改成滚动数组,提前处理出因子也可以减少枚举次数。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
int a[100005];
int f[1000005];
vector<int> y[1000005];
int main()
{
int n;
scanf("%d",&n);
int maxn=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
maxn=max(maxn,a[i]);
}
for(int i=1;i<=maxn;i++)
{
for(int j=1;j<=maxn/i;j++)
{
y[i*j].push_back(i);
}
}
f[0]=1;
for(int i=1;i<=n;i++)
{
for(int j=y[a[i]].size()-1;j>=0;j--)
{
int tmp=y[a[i]][j];
f[tmp]+=f[tmp-1];
f[tmp]%=1000000007;
}
}
int ans=0;
for(int i=1;i<=n;i++)
{
ans+=f[i];
ans%=1000000007;
}
cout<<ans<<endl;
return 0;
}
F - Compression
You are given a binary matrix A of size n×n. Let‘s denote an x-compression of the given matrix as a matrix B of size nx×nx such that for every i∈[1,n],j∈[1,n] the condition
A[i][j]=B[?*i**x*?][?*j**x*?] is met.
Obviously, x-compression is possible only if x divides n, but this condition is not enough. For example, the following matrix of size 2×2 does not have any 2-compression:
01
10
For the given matrix A, find maximum x such that an x-compression of this matrix is possible.
Note that the input is given in compressed form. But even though it is compressed, you‘d better use fast input.
Input
The first line contains one number n (4≤n≤5200) — the number of rows and columns in the matrix A. It is guaranteed that n is divisible by 4.
Then the representation of matrix follows. Each of n next lines contains n4 one-digit hexadecimal numbers (that is, these numbers can be represented either as digits from 0 to 9 or as uppercase Latin letters from A to F). Binary representation of each of these numbers denotes next 4 elements of the matrix in the corresponding row. For example, if the number B is given, then the corresponding elements are 1011, and if the number is 5, then the corresponding elements are 0101.
Elements are not separated by whitespaces.
Output
Print one number: maximum x such that an x-compression of the given matrix is possible.
思路:虽然题面说的不明觉厉,但实际上就是划分出元素全部相同的子矩阵。那么我们可以很显然的想到枚举原矩阵边长的因子,再检查子矩阵内元素是否相同。检查子矩阵可以用二维前缀和记录1的数量,再根据面积计算就可判断了。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
int mar[5205][5205];
int main()
{
int n;
scanf("%d",&n);
char tmp;
for(int i=1;i<=n;i++)
{
getchar();
for(int j=1;j<=n;j+=4)
{
tmp=getchar();
int t;
if(tmp>'9')
{
t=tmp-'A'+10;
}
else
{
t=tmp-'0';
}
for(int k=0;k<4;k++)
{
mar[i][j+k]=(t>>(3-k))&1;
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
mar[i][j]+=mar[i-1][j]+mar[i][j-1]-mar[i-1][j-1];
}
}
for(int i=n;i>=1;i--)
{
if(!(n%i))
{
bool flag=1;
for(int j=1;j*i<=n;j++)
{
for(int k=1;k*i<=n;k++)
{
int tmp=mar[i*j][i*k]-mar[i*j][i*(k-1)]-mar[i*(j-1)][i*k]+mar[i*(j-1)][i*(k-1)];
if(tmp!=i*i && tmp!=0)
{
flag=0;
}
}
}
if(flag)
{
cout<<i<<endl;
return 0;
}
}
}
return 0;
}
G - Make Product Equal One
You are given n numbers a1,a2,…,*a**n*. With a cost of one coin you can perform the following operation:
Choose one of these numbers and add or subtract 1 from it.
In particular, we can apply this operation to the same number several times.
We want to make the product of all these numbers equal to 1, in other words, we want a1?a2 … ?*a**n*=1.
For example, for n=3 and numbers [1,?3,0] we can make product equal to 1 in 3 coins: add 1 to second element, add 1 to second element again, subtract 1 from third element, so that array becomes [1,?1,?1]. And 1?(?1)?(?1)=1.
What is the minimum cost we will have to pay to do that?
Input
The first line contains a single integer n (1≤n≤105) — the number of numbers.
The second line contains n integers a1,a2,…,*a**n* (?109≤*a**i*≤109) — the numbers.
Output
Output a single number — the minimal number of coins you need to pay to make the product equal to 1.
思路:要求最后的结果为1,那么修改后的序列就应该只含-1和1,显而易见正数转化为1和负数转化为-1的代价最小。但如果一个序列中含有奇数个-1那么就需要将一个-1转换为1,如果存在0的话就可以将其转化为-1凑成偶数。所以可以线性的扫一遍,先记录转化到对应数的代价,最后再判断-1的数量。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
long long nums[100005];
int main()
{
int n;
scanf("%d",&n);
long long cost=0;
bool ifzero=0;
int cnt=0;
for(int i=1;i<=n;i++)
{
scanf("%lld",&nums[i]);
if(nums[i]>0)
{
cost+=nums[i]-1;
}
else if(nums[i]==0)
{
cost+=1;
ifzero=1;
}
else if(nums[i]<0)
{
cnt++;
cost+=(0-1-nums[i]);
}
}
if(cnt%2)
{
if(!ifzero)
{
cost+=2;
}
}
cout<<cost<<endl;
return 0;
}
H - Restricted RPS
Let n be a positive integer. Let a,b,c be nonnegative integers such that a+b+c=n.
Alice and Bob are gonna play rock-paper-scissors n times. Alice knows the sequences of hands that Bob will play. However, Alice has to play rock a times, paper b times, and scissors c times.
Alice wins if she beats Bob in at least ?n2? (n2 rounded up to the nearest integer) hands, otherwise Alice loses.
Note that in rock-paper-scissors:
- rock beats scissors;
- paper beats rock;
- scissors beat paper.
The task is, given the sequence of hands that Bob will play, and the numbers a,b,c, determine whether or not Alice can win. And if so, find any possible sequence of hands that Alice can use to win.
If there are multiple answers, print any of them.
Input
The first line contains a single integer t (1≤t≤100) — the number of test cases.
Then, t testcases follow, each consisting of three lines:
- The first line contains a single integer n (1≤n≤100).
- The second line contains three integers, a,b,c (0≤a,b,c≤n). It is guaranteed that a+b+c=n.
- The third line contains a string s of length n. s is made up of only ‘R‘, ‘P‘, and ‘S‘. The i-th character is ‘R‘ if for his i-th Bob plays rock, ‘P‘ if paper, and ‘S‘ if scissors.
Output
For each testcase:
- If Alice cannot win, print "NO" (without the quotes).
- Otherwise, print "YES" (without the quotes). Also, print a string t of length n made up of only ‘R‘, ‘P‘, and ‘S‘ — a sequence of hands that Alice can use to win. t must contain exactly a ‘R‘s, b ‘P‘s, and c ‘S‘s.
- If there are multiple answers, print any of them.
The "YES" / "NO" part of the output is case-insensitive (i.e. "yEs", "no" or "YEs" are all valid answers). Note that ‘R‘, ‘P‘ and ‘S‘ are case-sensitive.
思路:贪心,先放能赢的,放完后就随便放。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
char alc[105];
string bob;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
int cnt=0;
int a,b,c;
scanf("%d",&n);
scanf("%d%d%d",&a,&b,&c);
cin>>bob;
for(int i=0;i<n;i++)
{
if(bob[i]=='R' && b>0)
{
alc[i]='P';
b-=1;
}
else if(bob[i]=='P' && c>0)
{
alc[i]='S';
c-=1;
}
else if(bob[i]=='S' && a>0)
{
alc[i]='R';
a-=1;
}
else
{
alc[i]='N';
cnt++;
}
}
if(cnt<=(n/2))
{
cout<<"YES"<<endl;
for(int i=0;i<n;i++)
{
if(alc[i]=='N')
{
if(a>0)
{
cout<<'R';
a-=1;
}
else if(b>0)
{
cout<<'P';
b-=1;
}
else if(c>0)
{
cout<<'S';
c-=1;
}
}
else
{
cout<<alc[i];
}
}
cout<<endl;
}
else
{
cout<<"NO"<<endl;
}
}
return 0;
}
I - Make The Fence Great Again
You have a fence consisting of n vertical boards. The width of each board is 1. The height of the i-th board is ai. You think that the fence is great if there is no pair of adjacent boards having the same height. More formally, the fence is great if and only if for all indices from 2 to n, the condition ai?1≠*a**i* holds.
Unfortunately, it is possible that now your fence is not great. But you can change it! You can increase the length of the i-th board by 1, but you have to pay *b**i* rubles for it. The length of each board can be increased any number of times (possibly, zero).
Calculate the minimum number of rubles you have to spend to make the fence great again!
You have to answer q independent queries.
Input
The first line contains one integer q (1≤q≤3?105) — the number of queries.
The first line of each query contains one integers n (1≤n≤3?105) — the number of boards in the fence.
The following n lines of each query contain the descriptions of the boards. The i-th line contains two integers *a**i* and *b**i* (1≤ai,bi≤109) — the length of the i-th board and the price for increasing it by 1, respectively.
It is guaranteed that sum of all n over all queries not exceed 3?105.
It is guaranteed that answer to each query will not exceed 1018.
Output
For each query print one integer — the minimum number of rubles you have to spend to make the fence great.
思路:因为是要求是与相邻的两个高度不同,那么我们可以发现中间那块板最多只会增加2次。考虑dp,设f(i,j)为第i个木板增高j的最小花费,所以f(i,j)=min(f(i,j),f(i-1,k)+j*costi)
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
long long hi[300005];
long long cost[300005];
long long f[300005][3];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld %lld",&hi[i],&cost[i]);
f[i][0]=f[i][1]=f[i][2]=(1ll<<62);
}
f[1][0]=0;
f[1][1]=cost[1];
f[1][2]=cost[1]*2;
for(int i=2;i<=n;i++)
{
for(int j=0;j<3;j++)
{
for(int k=0;k<3;k++)
{
if(hi[i]+j!=hi[i-1]+k)
{
f[i][j]=min(f[i][j],f[i-1][k]+j*cost[i]);
}
}
}
}
cout<<min(min(f[n][0],f[n][1]),f[n][2])<<endl;
}
}
J - Dima and Salad
Dima, Inna and Seryozha have gathered in a room. That‘s right, someone‘s got to go. To cheer Seryozha up and inspire him to have a walk, Inna decided to cook something.
Dima and Seryozha have n fruits in the fridge. Each fruit has two parameters: the taste and the number of calories. Inna decided to make a fruit salad, so she wants to take some fruits from the fridge for it. Inna follows a certain principle as she chooses the fruits: the total taste to the total calories ratio of the chosen fruits must equal k. In other words, , where *a**j* is the taste of the j-th chosen fruit and *b**j* is its calories.
Inna hasn‘t chosen the fruits yet, she is thinking: what is the maximum taste of the chosen fruits if she strictly follows her principle? Help Inna solve this culinary problem — now the happiness of a young couple is in your hands!
Inna loves Dima very much so she wants to make the salad from at least one fruit.
Input
The first line of the input contains two integers n, k (1?≤?n?≤?100,?1?≤?k?≤?10). The second line of the input contains n integers a1,?a2,?...,?*a**n* (1?≤?*a**i?≤?100) — the fruits‘ tastes. The third line of the input contains n* integers b1,?b2,?...,?*b**n* (1?≤?*b**i?≤?100) — the fruits‘ calories. Fruit number i* has taste *a**i* and calories *b**i*.
Output
If there is no way Inna can choose the fruits for the salad, print in the single line number -1. Otherwise, print a single integer — the maximum possible sum of the taste values of the chosen fruits.
思路:完全没想到还能用背包来做,将题面给的式子转化为c=a-k*b,然后以a为价值c为重量做01背包就可以求出最大价值,因为背包容量为0,必须有负数,所以转化为2个01背包,1个装正的,1个装负的,最后将容量相同的价值加在一起,就可以得到最大值。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int a[105];
int b[105];
int f1[10005];
int f2[10005];
int main()
{
memset(f1,-0x3f3f3f3f,sizeof(f1));
memset(f2,-0x3f3f3f3f,sizeof(f2));
f1[0]=f2[0]=0;
int n,k;
scanf("%d %d",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++)
{
scanf("%d",&b[i]);
b[i]=a[i]-b[i]*k;
}
for(int i=1;i<=n;i++)
{
if(b[i]>=0)
{
for(int j=10000;j>=b[i];j--)
{
f1[j]=max(f1[j],f1[j-b[i]]+a[i]);
}
}
else
{
b[i]=-b[i];
for(int j=10000;j>=b[i];j--)
{
f2[j]=max(f2[j],f2[j-b[i]]+a[i]);
}
}
}
int ans=0;
for(int i=0;i<=10000;i++)
{
ans=max(ans,f1[i]+f2[i]);
}
if(ans==0)
{
cout<<-1<<endl;
}
else
{
cout<<ans<<endl;
}
return 0;
}
以上是关于2020 CDUT寒假集训第一场的主要内容,如果未能解决你的问题,请参考以下文章
Contest1692 - 2019寒假集训第三十一场 UPC 11075 Problem D小P的国际象棋