2019 16th浙江省省赛部分题解

B - Element Swapping

 

DreamGrid has an integer sequence  and he likes it very much. Unfortunately, his naughty roommate BaoBao swapped two elements  and  () in the sequence when DreamGrid wasn't at home. When DreamGrid comes back, he finds with dismay that his precious sequence has been changed into !

What's worse is that DreamGrid cannot remember his precious sequence. What he only remembers are the two values

Given the sequence after swapping and the two values DreamGrid remembers, please help DreamGrid count the number of possible element pairs  BaoBao swaps.

Note that as DreamGrid is poor at memorizing numbers, the value of  or  might not match the sequence, and no possible element pair can be found in this situation.

Two element pairs  () and  () are considered different if  or .

Input

There are multiple test cases. The first line of the input contains an integer , indicating the number of test cases. For each test case:

The first line contains three integers ,  and  (), indicating the length of the sequence and the two values DreamGrid remembers.

The second line contains  integers  (), indicating the sequence after swapping. It's guaranteed that  and .

It's guaranteed that the sum of  of all test cases will not exceed .

Output

For each test case output one line containing one integer, indicating the number of possible element pairs BaoBao swaps.

Sample Input

2
6 61 237
1 1 4 5 1 4
3 20190429 92409102
1 2 3

Sample Output

2
0

Hint

For the first sample test case, it’s possible that BaoBao swaps the 2nd and the 3rd element, or the 5th and the 6th element.

思路:我们很容易推到新数组的X,Y(与原数组的x,y对应)

  • 当(Y-y)==0&&(X-x)==0时,我们通过推导得知,ai==aj,那么ans=(num{ai}-1)*num{ai}/2;
  • (Y-y)!=0&&(X-x)!=0&&(Y-y)%(X-x)==0时。与原数组的x,y有如下关系:(Y-y)/(X-x)=ai+aj。ai和aj是交换的两个数。我们也很容易推到j=((X-x)+i*(a[j]-a[i]))/(a[j]-a[i]);如果j存在ans++;
  • 其余情况无解

推导过程:2019 16th浙江省省赛部分题解_第1张图片

我们推导时下标是按原数组来的,而程序中下标是按新数组来的,因此ai与aj互换 得到j=((X-x)+i*(aj-a[i]))/(aj-a[i]);

#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
map mp;
ll a[maxn];
int main()
{
	int t;
	ll x,y,X,Y,ans,cnt,n;
	scanf("%d",&t);
	while(t--)
	{
		X=0;Y=0;ans=0;
		mp.clear();
		scanf("%lld%lld%lld",&n,&x,&y);
		for(int i=1;i<=n;i++)
		{
			scanf("%lld",&a[i]);
			X+=a[i]*i;
			mp[a[i]]++;
			Y+=a[i]*a[i]*i;
		}
		if(x==X&&y==Y)
		{
			for(map::iterator it=mp.begin();it!=mp.end();it++)
                ans+=((it->second)-1)*(it->second)/2;
		}
		else if(x!=X&&y!=Y)
		{
			if((Y-y)%(X-x))
			{
				ans=0;
			}
			else
			{
				ll sum=(Y-y)/(X-x);
				for(int i=1;i<=n;i++)
				{
					ll aj=sum-a[i];
					if(aj-a[i]==0) continue;
					ll j=((X-x)+i*(aj-a[i]))/(aj-a[i]);
					if(j<=i||j>n) continue;
					if(aj==a[j]) ans++;
				}
			}
		}
		else ans=0;
		printf("%lld\n",ans);
	}
	return 0;
}

E - Sequence in the Pocket

 

DreamGrid has just found an integer sequence  in his right pocket. As DreamGrid is bored, he decides to play with the sequence. He can perform the following operation any number of times (including zero time): select an element and move it to the beginning of the sequence.

What's the minimum number of operations needed to make the sequence non-decreasing?

Input

There are multiple test cases. The first line of the input contains an integer , indicating the number of test cases. For each test case:

The first line contains an integer  (), indicating the length of the sequence.

The second line contains  integers  (), indicating the given sequence.

It's guaranteed that the sum of  of all test cases will not exceed .

Output

For each test case output one line containing one integer, indicating the answer.

Sample Input

2
4
1 3 2 4
5
2 3 3 5 5

Sample Output

2
0

Hint

For the first sample test case, move the 3rd element to the front (so the sequence become {2, 1, 3, 4}), then move the 2nd element to the front (so the sequence become {1, 2, 3, 4}). Now the sequence is non-decreasing.

For the second sample test case, as the sequence is already sorted, no operation is needed.

题意:给你n个数,你可以进行无限次操作(也可以不进行操作),每次你取其中一个数,把它放在序列的头上,问你最少需要多少次操作使得这个序列变成非严格递增序列

思路:找到所有逆序的数的中最大的那一个,位置记为pos;再找到它之前的比它大的最大的那个数的位置,记为maxx;这么说可能有些晦涩。举个例子:例如序列1 2 6 7 5 4,逆序的数有4和5,5之前比5大的有6和7,最大的那个是7,则pos=5,maxx=4,我们就找所有下标小于maxx的并且值小于a[pos]的个数,找所有下标大于maxx并且值小于等于a[pos]的个数。求和即可。

#include
#include
#include
#include
using namespace std;
const int maxn=1e5+10;
struct node{
	int val;
	int id;
}a[maxn];
bool cmp(node x,node y)
{
	if(x.val==y.val) return x.id1;i--)
		{
			if(a[i].val>a[i-1].val&&a[i].id

F - Abbreviation

In the Test of English as a Foreign Language (TOEFL), the listening part is very important but also very hard for most students since it is usually quite hard for them to remember the whole passage. To help themselves memorize the content, students can write down some necessary details. However, it is not easy to write down the complete word because of its length. That's why we decide to use the abbreviation to express the whole word.

It is very easy to get the abbreviation, all we have to do is to keep the consonant letters and erase the vowel. In the English alphabet, we regard 'a', 'e', 'i', 'y', 'o', 'u' as the vowels and the other letters as the consonants. For example, "subconscious" will be expressed as "sbcnscs".

However, there is one exception: if the vowel appears as the first letter, they should be kept instead of thrown away. For example, "oipotato" should be expressed as "optt".

Since you have learned how to use the abbreviation method, it's time for some exercises. We now present you  words in total, it's your task to express them in their abbreviation form.

Input

There are multiple test cases. The first line of the input contains an integer (about 100), indicating the number of test cases. For each test case:

The only line contains a string  () consisting of lowercase English letters, indicating the word which needs to be abbreviated.

Output

For each test case output one line containing one string, which is the correct abbreviation of the given word.

Sample Input

5
subconscious
oipotato
word
symbol
apple

Sample Output

sbcnscs
optt
wrd
smbl
appl

题意:去掉一个串中除第一个字符以外的所有带a,e,i,y,o,u的字符,并输出

思路:水

#include
#include
using namespace std;
const int maxn=110;
char s[maxn],tt[maxn];
int main()
{
	int t,cnt,n;
	scanf("%d",&t);
	while(t--)
	{
		cnt=0;
		scanf("%s",s);
		n=strlen(s);
		tt[cnt++]=s[0];
		for(int i=1;i

G - Lucky 7 in the Pocket

BaoBao loves number 7 but hates number 4, so he refers to an integer  as a "lucky integer" if  is divisible by 7 but not divisible by 4. For example, 7, 14 and 21 are lucky integers, but 1, 4 and 28 are not.

Today BaoBao has just found an integer  in his left pocket. As BaoBao dislikes large integers, he decides to find a lucky integer  such that  and  is as small as possible. Please help BaoBao calculate the value of .

Input

There are multiple test cases. The first line of the input is an integer  (about 100), indicating the number of test cases. For each test case:

The first and only line contains an integer  (), indicating the integer in BaoBao's left pocket.

Output

For each test case output one line containing one integer, indicating the value of .

Sample Input

4
1
7
20
28

Sample Output

7
7
21
35

题意:给你一个n,让你求第一个大于等于n的满足条件x%7==0&&x%4!=0的数x

思路:水

#include
#include
using namespace std;
int main()
{
	int t,n;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		while(1)
		{
			if(n%7==0&&n%4!=0)
			{
				printf("%d\n",n);
				break;
			}
			n++;
		}
	}
	return 0;
}

H - Singing Everywhere

Baobao loves singing very much and he really enjoys a game called Singing Everywhere, which allows players to sing and scores the players according to their performance.

Consider the song performed by Baobao as an integer sequence , where indicates the -th note in the song. We say a note  is a "voice crack" if ,  and . The more voice cracks BaoBao sings, the lower score he gets.

To get a higher score, BaoBao decides to delete at most one note in the song. What's the minimum number of times BaoBao sings a voice crack after this operation?

Input

There are multiple test cases. The first line of the input contains an integer (about 100), indicating the number of test cases. For each test case:

The first line contains one integer  (), indicating the length of the song.

The second line contains  integers  (), indicating the song performed by BaoBao.

It's guaranteed that at most 5 test cases have .

Output

For each test case output one line containing one integer, indicating the answer.

Sample Input

3
6
1 1 4 5 1 4
7
1 9 1 9 8 1 0
10
2 1 4 7 4 8 3 6 4 7

Sample Output

1
0
2

Hint

For the first sample test case, BaoBao does not need to delete a note. Because if he deletes no note, he will sing 1 voice crack (the 4th note), and no matter which note he deletes, he will also always sing 1 voice crack.

For the second sample test case, BaoBao can delete the 3rd note, and no voice cracks will be performed. Yay!

For the third sample test case, BaoBao can delete the 4th note, so that only 2 voice cracks will be performed (4 8 3 and 3 6 4).

题意:给你长度为n的序列,其中a[i-1]a[i+1]表示a[i]是一个crack,你可以进行一次操作,删除一个序列中的一个数(也可以不删),问你最小的crack是多少

思路:模拟操作即可

#include
#include
#include
using namespace std;
const int maxn=1e5+10;
int a[maxn],book[maxn];
int main()
{
	int n,t,ans,crack;
	scanf("%d",&t);
	while(t--)
	{
		ans=0;crack=0;
		memset(book,0,sizeof(book));
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
			scanf("%d",&a[i]);
		if(n<=2)
		{
			printf("0\n");
			continue;
		}
		for(int i=2;ia[i+1])
			{
				crack++;
				book[i]=1;
			}
		ans=crack;
		for(int i=3;ia[i+1]) tmp++;
				if(a[i-1]a[i+2]) tmp++;
			}
			else
			{
				if(book[i-1])
				{
					if(!(a[i-2]a[i+1])) tmp--;
				}
				else
				{
					if(a[i-2]a[i+1]) tmp++;
				}
				if(book[i+1])
				{
					if(!(a[i-1]a[i+2])) tmp--;
				}
				else
				{
					if(a[i-1]a[i+2]) tmp++;
				}
			}
			//printf("%d++++++\n",tmp);
			ans=min(ans,tmp);
		}
		if(book[2]) ans=min(crack-1,ans);
		if(book[n-1]) ans=min(crack-1,ans);
		if(n>3)
		{
			int tmp=crack;
			if(book[2])
			{
				if(!(a[1]a[4])) tmp--;
			}
			else
			{
				if(a[1]a[4]) tmp++;
			}
			ans=min(ans,tmp);
			tmp=crack;
			if(book[n-1])
			{
				if(!(a[n-3]a[n])) tmp--;
			}
			else
			{
				if(a[n-3]a[n]) tmp++;
			}
			ans=min(ans,tmp);
		}
		printf("%d\n",ans);
	}
	return 0;
}

I - Fibonacci in the Pocket

 

DreamGrid has just found a Fibonacci sequence  and two integers  and  in his right pocket, where  indicates the -th element in the Fibonacci sequence.

Please tell DreamGrid if  is even or is odd.

Recall that a Fibonacci sequence is an infinite sequence which satisfies ,  and  for all .

Input

There are multiple test cases. The first line of the input contains an integer (about 100), indicating the number of test cases. For each test case:

The first and only line contains two integers  and  (). Their meanings are described above.

Output

For each test case output one line. If  is even output "0" (without quotes); If  is odd output "1" (without quotes).

Sample Input

6
1 2
1 3
1 4
1 5
123456 12345678987654321
123 20190427201904272019042720190427

Sample Output

0
0
1
0
0
1

Hint

The first few elements of the Fibonacci sequence are: , , , , , ...

题意:给你一个区间[a,b],让你求下标在这个区间内的斐波那契数的和是奇数还是偶数

思路:打表找规律

  • 当(b-a+1)%3==0时,一定为偶数
  • 当(b-a+1)%3==1时,当a%3==0是一定为偶数,其余情况为奇数
  • 当(b-a+1)%3==2时,当a%3==1时一定为偶数,其余情况为奇数
import java.util.*;
import java.math.*;
public class Main {	
	public static void main(String[] args) {
		Scanner reader = new Scanner(System.in);
		int T=reader.nextInt();
		for(int i=0;i

J - Welcome Party

The 44th World Finals of the International Collegiate Programming Contest (ICPC 2020) will be held in Moscow, Russia. To celebrate this annual event for the best competitive programmers around the world, it is decided to host a welcome party for all  participants of the World Finals, numbered from  to  for convenience.

The party will be held in a large hall. For security reasons, all participants must present their badge to the staff and pass a security check in order to be admitted into the hall. Due to the lack of equipment to perform the security check, it is decided to open only one entrance to the hall, and therefore only one person can enter the hall at a time.

Some participants are friends with each other. There are  pairs of mutual friendship relations. Needless to say, parties are more fun with friends. When a participant enters the hall, if he or she finds that none of his or her friends is in the hall, then that participant will be unhappy, even if his or her friends will be in the hall later. So, one big problem for the organizer is the order according to which participants enter the hall, as this will determine the number of unhappy participants. You are asked to find an order that minimizes the number of unhappy participants. Because participants with smaller numbers are more important (for example the ICPC director may get the number 1), if there are multiple such orders, you need to find the lexicographically smallest one, so that important participants enter the hall first.

Please note that if participant  and  are friends, and if participant  and  are friends, it's NOT necessary that participant  and  are friends.

Input

There are multiple test cases. The first line of the input contains a positive integer , indicating the number of cases. For each test case:

The first line contains two integers  and  (), the number of participants and the number of friendship relations.

The following  lines each contains two integers  and  (), indicating that the -th and the -th participant are friends. Each friendship pair is only described once in the input.

It is guaranteed that neither the sum of  nor the sum of  of all cases will exceed .

Output

For each case, print a single integer on the first line, indicating the minimum number of unhappy participants. On the second line, print a permutation of  to separated by a space, indicating the lexicographically smallest ordering of participants entering the hall that achieves this minimum number.

Consider two orderings  and , we say  is lexicographically smaller than , if there exists an integer  (), such that  holds for all , and .

Please, DO NOT output extra spaces at the end of each line, or your solution may be considered incorrect!

Sample Input

2
4 3
1 2
1 3
1 4
4 2
1 2
3 4

Sample Output

1
1 2 3 4
2
1 2 3 4

题意:给你n,m,分别表示有n个人和有m个关系,每个关系a,b表示a和b是朋友(不具有传递性,例如:ab是朋友,bc是朋友,ac不是朋友),这些人按顺序进入一个会场,如果会场里的人没有他的朋友,那么这个人会不高兴。问你一种进入顺序,使得不高兴的人的数目最少,并且进入的人的编号的顺序按字典序排序最小。

并查集+优先队列+建图

思路:我们可以想到,朋友之间的关系用并查集维护一个集合,我们很容易想到,每个集合中第一个进入会场的人一定是不高兴的(因为他和别的集合的所有人都不认识),并且集合中只要有一个人进入会场,这个集合中的所有人都可以高兴地进入会场。我们就知道不高兴的人数就是并查集集合的个数。那么我们怎么找这个最小字典序顺序呢?我们可以想到优先队列。首先,我们将并查集每个集合的代表元素设为这个集合中的最小元素。每次弹出一个最小的元素输出,然后将这个元素所邻接的所有的点入队,直到所有的点都被输出。

#include
#include
#include
#include
using namespace std;
const int maxn=1e6+2;
struct node{
	int id;
	int next;
}side[maxn*2];
priority_queue,greater > q;
int head[maxn],pre[maxn],book[maxn],cnt,n;
void init()
{
	for(int i=0;i<=n;i++)
	{
		pre[i]=i;
		head[i]=-1;
		book[i]=0;
	}
	cnt=0;
}
void add(int x,int y)
{
	side[cnt].id=y;
	side[cnt].next=head[x];
	head[x]=cnt++;
}
int find(int x)
{
	if(pre[x]!=x)
		pre[x]=find(pre[x]);
	return pre[x];
}
void union1(int x,int y)
{
	int fx=find(x),fy=find(y);
	if(fx!=fy)
	{
		if(fx>fy)
		{
			pre[fx]=fy;
		}
		else
		{
			pre[fy]=fx;
		}
	}
}
void solve(int x)
{
	book[x]=1;
	for(int i=head[x];i!=-1;i=side[i].next)
	{
		int y=side[i].id;
		if(book[y]) continue;
		q.push(y);
		book[y]=1;
	}
}
int main()
{
	int t,m,x,y,un;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		init();
		un=0;
		while(q.size()) q.pop();
		for(int i=1;i<=m;i++)
		{
			scanf("%d%d",&x,&y);
			add(x,y);
			add(y,x);
			union1(x,y);
		}
		for(int i=1;i<=n;i++)
		{
			if(pre[i]==i)
			{
				un++;
				q.push(i);
			}
		}
		int cont=0;
		printf("%d\n",un);
		while(q.size())
		{
			if(cont==0)
			{
				printf("%d",q.top());
				cont++;
			}
			else
			{
				printf(" %d",q.top());
				cont++;
			}
			int tmp=q.top();
			q.pop();
			solve(tmp);
		}
		printf("\n");
	}
	return 0;
}

K - Strings in the Pocket

BaoBao has just found two strings  and  in his left pocket, where  indicates the -th character in string , and  indicates the -th character in string .

As BaoBao is bored, he decides to select a substring of  and reverse it. Formally speaking, he can select two integers  and  such that  and change the string to .

In how many ways can BaoBao change  to  using the above operation exactly once? Let  be an operation which reverses the substring , and  be an operation which reverses the substring . These two operations are considered different, if  or .

Input

There are multiple test cases. The first line of the input contains an integer , indicating the number of test cases. For each test case:

The first line contains a string  (), while the second line contains another string  (). Both strings are composed of lower-cased English letters.

It's guaranteed that the sum of  of all test cases will not exceed .

Output

For each test case output one line containing one integer, indicating the answer.

Sample Input

2
abcbcdcbd
abcdcbcbd
abc
abc

Sample Output

3
3

Hint

For the first sample test case, BaoBao can do one of the following three operations: (2, 8), (3, 7) or (4, 6).

For the second sample test case, BaoBao can do one of the following three operations: (1, 1), (2, 2) or (3, 3).

 

题意:给你两个字符串,可以选择一个串a的一个字串进行一次反转操作,使串a变成串b,问你有多少种转换方式,如果无法转换,输出0;

思路:马拉车算法

  • 如果串a和串b相等,那么只要选择的字串是回文串,就可以旋转,那么就找这个马拉车算法中所得新串里每个字符能够形成的回文串半径长度的一半,结果为这些数值之和
  • 如果串a和串b不相等,那么就找最开始不相等那个字符和最后不相等的那个字符,分别向前向后找,如果找的那两个字符相等,ans++,最后结果为ans+1
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn=2e6+10;
char ma[maxn*2],a[maxn],b[maxn];
int mp[maxn*2];
int manacher(char s[],int len)
{
	int l=0;
	ma[l++]='$';
	ma[l++]='#';
	for(int i=0;ii?min(mp[2*id-i],mx-i):1;
		while(ma[i+mp[i]]==ma[i-mp[i]]) mp[i]++;
		if(i+mp[i]>mx)
		{
			mx=i+mp[i];
			id=i;
		}
	}
	return 2*len+1;
}
int main()
{
	int len,t,flag,le,ri;
	ll ans;
	scanf("%d",&t);
	while(t--)
	{
		flag=0;ans=0;
		scanf("%s",a);scanf("%s",b);
		if(strcmp(a,b)==0) flag=1;
		len=strlen(a);
		if(flag)
		{
			int tt=manacher(a,len);
			for(int i=0;i=0;i--)
			{
				if(a[i]!=b[i])
				{
					r=i;
					break;
				}
			}
			int tmpp=0;
			for(int i=l;i<=r;i++)
			{
				if(a[i]!=b[r+l-i])
				{
					tmpp=1;
					break;
				}
			}
			if(tmpp==1)
			{
				printf("0\n");
				continue;
			}
			l--;r++;
			while(l>=0&&r

 

你可能感兴趣的:(省赛)