SCAU 周训二

A - A

1.题目描述:
*Pashmak decided to give Parmida a pair of flowers from the garden. There are n flowers in the garden and the i-th of them has a beauty number bi. Parmida is a very strange girl so she doesn’t want to have the two most beautiful flowers necessarily. She wants to have those pairs of flowers that their beauty difference is maximal possible!

Your task is to write a program which calculates two things:

1.The maximum beauty difference of flowers that Pashmak can give to Parmida.
2.The number of ways that Pashmak can pick the flowers. Two ways are considered different if and only if there is at least one flower that is chosen in the first way and not chosen in the second way.

Input
The first line of the input contains n (2 ≤ n ≤ 2·105). In the next line there are n space-separated integers b1, b2, …, bn (1 ≤ bi ≤ 109).

Output
The only line of output should contain two integers. The maximum beauty difference and the number of ways this may happen, respectively.

Examples

Input
2
1 2

Output
1 1

Input
3
1 4 5

Output
4 1

Input
5
3 1 2 3 1

Output
2 4

Note
In the third sample the maximum beauty difference is 2 and there are 4 ways to do this:
1.choosing the first and the second flowers;
2.choosing the first and the fifth flowers;
3.choosing the fourth and the second flowers;
4.choosing the fourth and the fifth flowers.

2.题意:
一个浪漫的求爱者(舔狗)想送一束花给一位奇怪的女士——她喜欢两朵花的美丽程度最大。那么先生无奈只能求助于你啦——请问有多少种方法呢?

3.思路:
(神坑)签到题,求最大最小值,然后记录数量。但是要考虑最大最小值相等的时候,由于两朵花必须以不同的身份被选出,所以只能是C2n(排列数)啦——也就是(n*(n-1)/2);

4.代码:

//A
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define FAST ios::sync_with_stdio(false)
using namespace std;
const int MAX_N = 2*100000+5;
int b[MAX_N];
int main()
{
	//freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
	unsigned long long n,Min=0x3f3f3f3f,t_min=0,Max=0,t_max=0;
	cin>>n;
	for(int i=0;i<n;++i)
		cin>>b[i];
	sort(b,b+n);
	Max=b[n-1],Min=b[0];
	for(int i=0;i<n;++i)
		if(b[i]==Min)
			t_min++;
		else
			break;
	for(int i=n-1;i>=0;--i)
		if(b[i]==Max)
			t_max++;
		else
			break;
	cout<<Max-Min<<" ";
	if(Max==Min)
		cout<<n*(n-1)/2<<endl;
	else
		cout<<t_min*t_max<<endl;
	return 0;
}

B - B

1.题目描述:
There are so many different religions in the world today that it is difficult to keep track of them all. You are interested in finding out how many different religions students in your university believe in.

You know that there are n students in your university (0 < n <= 50000). It is infeasible for you to ask every student their religious beliefs. Furthermore, many students are not comfortable expressing their beliefs. One way to avoid these problems is to ask m (0 <= m <= n(n-1)/2) pairs of students and ask them whether they believe in the same religion (e.g. they may know if they both attend the same church). From this data, you may not know what each person believes in, but you can get an idea of the upper bound of how many different religions can be possibly represented on campus. You may assume that each student subscribes to at most one religion.

Input
The input consists of a number of cases. Each case starts with a line specifying the integers n and m. The next m lines each consists of two integers i and j, specifying that students i and j believe in the same religion. The students are numbered 1 to n. The end of input is specified by a line in which n = m = 0.

Output
For each test case, print on a single line the case number (starting with 1) followed by the maximum number of different religions that the students in the university believe in.

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

Sample Output
Case 1: 1
Case 2: 7

Hint
Huge input, scanf is recommended.

2.题意:
你想调查别人的宗教信仰,但是呢,直接问好像不太好。所以你就找了一对人,问他们宗教信仰一不一样,进而求出不一样信仰的上界。

3.思路:
典型的并查集啦,如果两个人信仰一样,可以看做一类,然后看一下有多少种分类。

4.代码:

//B
#include<iostream>
#include<cstdio>
using namespace std;
const int MAX_N = 50000+5;
int n,m,x,y,tot=1;
int par[MAX_N];
int uni(int root)
{
	int son=root,tmp;
	while(root!=par[root])
		root=par[root];
	while(son!=root)
	{
		tmp=par[son];
		par[son]=root;
		son=tmp;
	}
	return root;
}
int main()
{
	//freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
	while(cin>>n>>m&&n&&m)
	{
		int ans=n,root1,root2;
		for(int i=0;i<n;++i)
			par[i]=i;
		for(int i=0;i<m;++i)
		{
			cin>>x>>y;
			root1=uni(x);
			root2=uni(y);
			if(root1!=root2)
			{
				par[root1]=root2;
				ans--;
			}
		}
		printf("Case %d: %d\n",tot++,ans);
	}
	return 0;
}

C - C

1.题目描述:
Two bored soldiers are playing card war. Their card deck consists of exactly n cards, numbered from 1 to n, all values are different. They divide cards between them in some manner, it’s possible that they have different number of cards. Then they play a “war”-like card game.
The rules are following. On each turn a fight happens. Each of them picks card from the top of his stack and puts on the table. The one whose card value is bigger wins this fight and takes both cards from the table to the bottom of his stack. More precisely, he first takes his opponent’s card and puts to the bottom of his stack, and then he puts his card to the bottom of his stack. If after some turn one of the player’s stack becomes empty, he loses and the other one wins.
You have to calculate how many fights will happen and who will win the game, or state that game won’t end.

Input
First line contains a single integer n (2 ≤ n ≤ 10), the number of cards.
Second line contains integer k1 (1 ≤ k1 ≤ n - 1), the number of the first soldier’s cards. Then follow k1 integers that are the values on the first soldier’s cards, from top to bottom of his stack.
Third line contains integer k2 (k1 + k2 = n), the number of the second soldier’s cards. Then follow k2 integers that are the values on the second soldier’s cards, from top to bottom of his stack.

All card values are different.

Output
If somebody wins in this game, print 2 integers where the first one stands for the number of fights before end of game and the second one is 1 or 2 showing which player has won.
If the game won’t end and will continue forever output  - 1.

Examples
Input
4
2 1 3
2 4 2

Output
6 2

Input
3
1 2
2 1 3

Output
-1

2.题意:
两个人分别在自己队列里抽卡,队列里的卡是从1-n不同的卡,如果自己的卡比对方大就可以占为己有,谁先莫得卡谁就输。

3.思路:
一个很简单的模拟题,用两个队列模拟进出卡,然后当cnt(回合数)超过固定次数时就退出。

4.代码:

//C
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define FAST ios::sync_with_stdio(false)
using namespace std;
int main()
{
	//freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
	int n,k1,k2,tmp,cnt=0;
	queue<int> q1,q2;
	cin>>n;
	cin>>k1;
	for(int i=0;i<k1;++i)
	{
		cin>>tmp;
		q1.push(tmp);
	}
	cin>>k2;
	for(int i=0;i<k2;++i)
	{
		cin>>tmp;
		q2.push(tmp);
	}
	while(true)
	{
		if(q1.front()>q2.front())
		{
			q1.push(q2.front());
			q2.pop();
			q1.push(q1.front());
			q1.pop();
			cnt++;
		}
		else
		{
			q2.push(q1.front());
			q1.pop();
			q2.push(q2.front());
			q2.pop();
			cnt++;
		}
		if(q1.empty()||q2.empty())
		{
			cout<<cnt<<" "<<(q1.empty()?2:1)<<endl;
			break;
		}
		if(cnt>500)
		{
			cout<<"-1"<<endl;
			break;
		}
	}
	return 0;
}

D - D

1.题目描述:
Vasya has n days of vacations! So he decided to improve his IT skills and do sport. Vasya knows the following information about each of this n days: whether that gym opened and whether a contest was carried out in the Internet on that day. For the i-th day there are four options:
1.on this day the gym is closed and the contest is not carried out;
2.on this day the gym is closed and the contest is carried out;
3.on this day the gym is open and the contest is not carried out;
4.on this day the gym is open and the contest is carried out.
On each of days Vasya can either have a rest or write the contest (if it is carried out on this day), or do sport (if the gym is open on this day).
Find the minimum number of days on which Vasya will have a rest (it means, he will not do sport and write the contest at the same time). The only limitation that Vasya has — he does not want to do the same activity on two consecutive days: it means, he will not do sport on two consecutive days, and write the contest on two consecutive days.
Input
The first line contains a positive integer n (1 ≤ n ≤ 100) — the number of days of Vasya’s vacations.
The second line contains the sequence of integers a1, a2, …, an (0 ≤ ai ≤ 3) separated by space, where:

1.ai equals 0, if on the i-th day of vacations the gym is closed and the contest is not carried out;
2.ai equals 1, if on the i-th day of vacations the gym is closed, but the contest is carried out;
3.ai equals 2, if on the i-th day of vacations the gym is open and the contest is not carried out;
4.ai equals 3, if on the i-th day of vacations the gym is open and the contest is carried out.

Output
Print the minimum possible number of days on which Vasya will have a rest. Remember that Vasya refuses:
to do sport on any two consecutive days,
to write the contest on any two consecutive days.

Examples
Input
4
1 3 2 0

Output
2

Input
7
1 3 3 2 1 2 3

Output
0

Input
2
2 2

Output
1

Note
In the first test Vasya can write the contest on the day number 1 and do sport on the day number 3. Thus, he will have a rest for only 2 days.
In the second test Vasya should write contests on days number 1, 3, 5 and 7, in other days do sport. Thus, he will not have a rest for a single day.
In the third test Vasya can do sport either on a day number 1 or number 2. He can not do sport in two days, because it will be contrary to the his limitation. Thus, he will have a rest for only one day.

2.题意:
一个程序员他 放!假!啦!(假的),不过他希望自己的假期过得充实且愉悦,所以安排了一波假期计划(咕咕咕),他记录了比赛和jam开始的日期,他一天只能参加一项且两天不能参加同一项项目(毕竟不是所有人都是ak怪或者健身达人)。问他最少能咕咕咕(休息)几天?

3.思路:
一开始想多了,以为dp,后来发现不用,前面一天完全决定了后面一天所以记录下前一天的信息进行比对就好啦,由于连续的3必定可以,所以考虑前一个与后一个同为 1 或者 2 的情况,将今天改成0。如果今天是3,那么就和前一天不同就好了。

4.代码:

//D
#include<iostream>
using namespace std;
int main()
{
	int n,tmp=0,pre=0,cnt=0;
	cin>>n;
	for(int i=0;i<n;++i)
	{
		pre=tmp;
		cin>>tmp;
		if(i)
		{
			if(pre==tmp&&tmp!=3) tmp=0;
			else if(pre!=3&&tmp==3) tmp=3-pre;
		}
		if(!tmp) cnt++;
	}
	cout<<cnt<<endl;
	return 0;
}

E - E

1.题意描述:
There are N villages, which are numbered from 1 to N, and you should build some roads such that every two villages can connect to each other. We say two village A and B are connected, if and only if there is a road between A and B, or there exists a village C such that there is a road between A and C, and C and B are connected.
We know that there are already some roads between some villages and your job is the build some roads such that all the villages are connect and the length of all the roads built is minimum.

Input
The first line is an integer N (3 <= N <= 100), which is the number of villages. Then come N lines, the i-th of which contains N integers, and the j-th of these N integers is the distance (the distance should be an integer within [1, 1000]) between village i and village j.
Then there is an integer Q (0 <= Q <= N * (N + 1) / 2). Then come Q lines, each line contains two integers a and b (1 <= a < b <= N), which means the road between village a and village b has been built.

Output
You should output a line contains an integer, which is the length of all the roads to be built such that all the villages are connected, and this value is minimum.

Sample Input
3
0 990 692
990 0 179
692 179 0
1
1 2

Sample Output
179

2.题意:
有一个村庄想修路,希望彼此之间能相互连通,他们已经修好部分路,想问完全修好的最小代价?(这题多Case问题。)

3.思路:
典型的 最小生成树问题,题目简化了一部分,用prim算法可能会比较麻烦,因为要筛选顶点;有了边我们可以直接用 kruskal 算法

4.代码:

//E
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define FAST ios::sync_with_stdio(false)
using namespace std;
const int MAX_N = 100+5;
int N,Q,a,b,p[MAX_N];
int f(int x){return (p[x]==x?x:p[x]=f(p[x]));}
struct edge{int u,v,w;} map[MAX_N*MAX_N];
bool cmp(edge& a,edge& b){return a.w<b.w;}
int main()
{
	//freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
	while(~scanf("%d",&N))
	{
		int tmp,ans=0,k=0,pos=0;
		for(int i=1;i<=N;++i)
			p[i]=i;
		for(int i=1;i<=N;++i)
			for(int j=1;j<=N;++j)
			{
				cin>>tmp;
				if(i<j)
				{
					map[pos].u=i;
					map[pos].v=j;
					map[pos].w=tmp;
					pos++;
				}
			}
		sort(map,map+pos,cmp);
		cin>>Q;
		for(int i=0;i<Q;++i)
		{
			cin>>a>>b;
			int x=f(a),y=f(b);
			if(x!=y&&++k) p[x]=y;
		}
		for(int i=0;i<pos;++i)
		{
			if(k==N-1) break;
			int x=f(map[i].u),y=f(map[i].v);
			if(x!=y&&++k)
			{
				p[x]=y;
				ans+=map[i].w;
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}

F - F

1.题目描述:
DZY loves chessboard, and he enjoys playing with it.
He has a chessboard of n rows and m columns. Some cells of the chessboard are bad, others are good. For every good cell, DZY wants to put a chessman on it. Each chessman is either white or black. After putting all chessmen, DZY wants that no two chessmen with the same color are on two adjacent cells. Two cells are adjacent if and only if they share a common edge.
You task is to find any suitable placement of chessmen on the given chessboard.

Input
The first line contains two space-separated integers n and m (1 ≤ n, m ≤ 100).
Each of the next n lines contains a string of m characters: the j-th character of the i-th string is either “.” or “-”. A “.” means that the corresponding cell (in the i-th row and the j-th column) is good, while a “-” means it is bad.

Output
Output must contain n lines, each line must contain a string of m characters. The j-th character of the i-th string should be either “W”, “B” or “-”. Character “W” means the chessman on the cell is white, “B” means it is black, “-” means the cell is a bad cell.
If multiple answers exist, print any of them. It is guaranteed that at least one answer exists.

Examples
Input
1 1
.

Output
B

Input
2 2

Output
BW
WB

Input
3 3
.-.
(三道杠) - - -
(两道杠)- -.

Output
B-B
(三道杠)- - -
–B
Note
In the first sample, DZY puts a single black chessman. Of course putting a white one is also OK.

In the second sample, all 4 cells are good. No two same chessmen share an edge in the sample output.

In the third sample, no good cells are adjacent. So you can just put 3 chessmen, no matter what their colors are.

2.题意:
大概是有一个棋盘,有受损的“-”,还有没有受损的“.”,要把他们涂成黑(B)白(W);任意两格相邻的不能同色(共享一条边)。求任意涂色情况。

3.思路:
一开始还傻乎乎地分类讨论,结果看大佬的,秒解(Orz)。思路超简单,你怎么给普通棋盘涂色?直接分单双呗,然后加上障碍就完事了。完全思维题…

4.代码:

//F
#include<iostream>
#include<string>
#define FAST ios::sync_with_stdio(false)
using namespace std;
const int MAX_N=100+5;
char s[MAX_N][MAX_N];
int main()
{
	//freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
	int n,m;
	cin>>n>>m;
	for(int i=0;i<n;++i,cout<<endl)
		for(int j=0;j<m;++j)
			if(cin>>s[i][j]&&s[i][j]=='-') cout<<s[i][j];
			else
				if((i+j)&1)
					cout<<"B";
				else
					cout<<"W";
	return 0;
}

G - G

1.题目描述:
Ignatius has just come back school from the 30th ACM/ICPC. Now he has a lot of homework to do. Every teacher gives him a deadline of handing in the homework. If Ignatius hands in the homework after the deadline, the teacher will reduce his score of the final test. And now we assume that doing everyone homework always takes one day. So Ignatius wants you to help him to arrange the order of doing homework to minimize the reduced score.

Input
The input contains several test cases. The first line of the input is a single integer T that is the number of test cases. T test cases follow.
Each test case start with a positive integer N(1<=N<=1000) which indicate the number of homework… Then 2 lines follow. The first line contains N integers that indicate the deadlines of the subjects, and the next line contains N integers that indicate the reduced scores.

Output
For each test case, you should output the smallest total reduced score, one line per test case.

Sample Input
3
3
3 3 3
10 5 1
3
1 3 1
6 2 3
7
1 4 6 4 2 4 3
3 2 1 7 6 5 4

Sample Output
0
3
5

2.题意:
你呢是一个ACMer,你有好多功课要做,每门课都有ddl,迟交有惩罚哟。那么聪明的你如何规划使得惩罚最小呢?

3.思路:
这题一看秒想到dp或贪心,但是考虑到这个题目的特性,直接贪心。因为你可以相当于丢出一天来换另一天嘛。当时想到的就是贪心+优先队列。但是因为时间不够而且被H题题设弄得心态爆炸,故而一开始弄错了优先的次序。真正来说挺简单的——先按照ddl的时间来排序,ddl中间有很多空隙,可以继续填上下一天来保证前面都是满的。这样做是为了方便之后调出最小惩罚。在保证满的前提下,即第i天的ddl就是i,把它们丢进优先队列里,按照惩罚小优先排序如果碰到一天的ddl大于i,那么因为前面放满了,所以我们先把它放进去(有可能它的惩罚最小),然后替换掉最小惩罚的那一天,这样保证前面也还是满的(表明我们尽量避免了额外空隙的惩罚),惩罚也最小。

4.代码:

//G
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define FAST ios::sync_with_stdio(false)
using namespace std;
struct Node
{
	int ddl,rdu;
	bool operator < (const Node&x)const
	{
			return rdu > x.rdu;
	}
}work[1005];
bool cmp(const Node &a,const Node &b)
{
	if(a.ddl!=b.ddl)
		return a.ddl<b.ddl;
	else
		return a.rdu<b.rdu;
}
int N;
int main()
{
	//freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
	long long Case;
	scanf("%lld",&Case);
	while(Case--)
	{
		int ans=0;
		cin>>N;
		priority_queue<Node> q;
		for(int i=0;i<N;++i)
			cin>>work[i].ddl;
		for(int i=0;i<N;++i)
			cin>>work[i].rdu;
		sort(work,work+N,cmp);
		for(int i=0;i<N;++i)
		{
			if((int)q.size()<work[i].ddl)
				q.push(work[i]);
			else
			{
				q.push(work[i]);
				ans+=q.top().rdu;
				q.pop();
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}

H - H

1.题目描述:
To improve the organization of his farm, Farmer John labels each of his N (1 <= N <= 5,000) cows with a distinct serial number in the range 1…20,000. Unfortunately, he is unaware that the cows interpret some serial numbers as better than others. In particular, a cow whose serial number has the highest prime factor enjoys the highest social standing among all the other cows.
(Recall that a prime number is just a number that has no divisors except for 1 and itself. The number 7 is prime while the number 6, being divisible by 2 and 3, is not).
Given a set of N (1 <= N <= 5,000) serial numbers in the range 1…20,000, determine the one that has the largest prime factor.

Input

  • Line 1: A single integer, N
  • Lines 2…N+1: The serial numbers to be tested, one per line

Output

  • Line 1: The integer with the largest prime factor. If there are more than one, output the one that appears earliest in the input file.

Sample Input
4
36
38
40
42

Sample Output
38

2.题意:
要求我们求出给定数字的最大素因子。

3.思路:
神坑!!!这题是多CASE输入!!!(听取 WA 声一片),模拟题,总体就是先打表,分读进来是素数还是不是素数,是就比大小,否则就丢进循环里,如果能找到更多的素数就更新。(气得老子想杀人。)

4.代码:

//H
#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;
const int MAX_N=20000+5;
bool prim[MAX_N];
int N,ans,tmp,max_fac;
int main()
{	
	//freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
	for(int i=1;i<MAX_N;++i)
		prim[i]=1;
	for(int i=2;i<MAX_N;++i)
		for(int j=2*i;j<MAX_N;j+=i)
			prim[j]=0;
	while(scanf("%d",&N)!=EOF)
	{
		ans=0,max_fac=0,tmp=0;
		while(N--)
		{
			cin>>tmp;
			if(prim[tmp]&&max_fac<tmp)
			{
				ans=tmp;
				max_fac=tmp;
			}
			else
			{
				for(int i=max_fac+1;i<tmp;++i)
					if(prim[i]&&!(tmp%i))
					{
						max_fac=i;
						ans=tmp;
					}
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值