1. 程式人生 > >浪在ACM第七次訓練純C題解

浪在ACM第七次訓練純C題解

A Coins
You have unlimited number of coins with values 1,2,…,n. You want to select some set of coins having the total value of S.

It is allowed to have multiple coins with the same value in the set. What is the minimum number of coins required to get sum S?
Input
The only line of the input contains two integers nn and SS (1≤n≤100000, 1≤S≤10的9次方)
Output


Print exactly one integer — the minimum number of coins required to obtain sum SS.
Examples
Input
5 11
Output
3
Input
6 16
Output
3

A題就不說什麼了。。。

#include <stdio.h>
int main()
{
	int j,n,s,sum=0,cnt=0;
	scanf("%d %d",&n,&s);
	for(int i=n;i>=1;i--)
	{
		j=s/i;
		for(int k=1;k<=j;k++
) { sum=sum+i;s=s-i;cnt++; } } printf("%d",cnt); return 0; }

B Views Matter
You came to the exhibition and one exhibit has drawn your attention. It consists of nn stacks of blocks, where the ii-th stack consists of aiai blocks resting on the surface.

The height of the exhibit is equal to mm. Consequently, the number of blocks in each stack is less than or equal to mm.

There is a camera on the ceiling that sees the top view of the blocks and a camera on the right wall that sees the side view of the blocks.
在這裡插入圖片描述
Find the maximum number of blocks you can remove such that the views for both the cameras would not change.

Note, that while originally all blocks are stacked on the floor, it is not required for them to stay connected to the floor after some blocks are removed. There is no gravity in the whole exhibition, so no block would fall down, even if the block underneath is removed. It is not allowed to move blocks by hand either.
Input
The first line contains two integers nn and mm (1≤n≤100000, 1≤m≤10的9次方) — the number of stacks and the height of the exhibit.

The second line contains nn integers a1,a2,…,ana1,a2,…,an (1≤ai≤m) — the number of blocks in each stack from left to right.
Output
Print exactly one integer — the maximum number of blocks that can be removed.
Examples
Input
5 6
3 3 3 3 3
Output
10
Input
3 5
1 2 4
Output
3
Input
5 5
2 3 1 4 4
Output
9
Input
1 1000
548
Output
0
Input
3 3
3 1 1
Output
1

B題先重複一下凱哥昨天講的思路:先把每一堆排好序,然後逐個判斷,從1----n-1列的判斷方式是如果本列的塊數比上一列的最高層數大,則最高層數加一,並且每次判斷讓必須留下的塊數+1(其實易知1~n-1列都是隻有一個的,可以直接讓計數器的個數等於n-1),再判斷第n列,第n列的需要必須留下的塊數為:第n列的個數減去最高層數(這一點看下面那張圖就很好理解),最後輸出總塊數減去必須留下的塊數即為最多能去除的塊數。
我感覺我還得解釋一下我這裡說的最高層的意思就是下面圖中前i列在保留完畢後第i列保留塊的高度,比如下面這個圖,第n-1列保留塊的高度為9,則最高層數就是9

在這裡插入圖片描述
如上圖,每一列的塊數分別為 1 6 6 9 12 12 12 12 13 16
由題目裡所得出的規律可知第1~n-1列必須留下的個數就是n-1,所以cnt先等於n-1=9,然後看最後一列,最後一列的必須留下的塊數取決於兩個因素,一是這一列本身的塊數,二是第n-1列的層數,因為為了保持側檢視的不變,最後一列高於最高層數的所有塊都要保留,所以最後一列必須保留的塊數為16-9=7,因此總共必須保留的塊數cnt=9+7=16,用總塊數99-16=83即為最多可以去除的塊數。其他情況都是這樣,有一個例外就是如果最後一層的個數和最高層數相等,那最後一層必須留下的塊數為1(看圖就能明白,把最後一列改成13看一看)。
還有兩個注意事項:1.ai和m的大小都是小於10的9次方,資料比較大,需要定long long int(我為了方便把下面程式的整數基本都定成long long int 了)。
2.注意到n的最大取值能到10W,那好幾萬個數排序用普通的排序必然會超時了,這裡要用快速排序,C語言庫中也有自帶的快速排序,不過要自己帶上一小段程式碼判斷升序還是降序,具體看程式碼。
建議直接記住C快排函式的用法。

#include <stdio.h>
#include <stdlib.h> //快速排序在這個標頭檔案裡
#define MAXN 100000
long long int a[MAXN];
int comp(const void*a,const void*b)
{
	return *(int*)a-*(int*)b;
} //自己寫上這一段程式碼,判斷快排是升序還是降序,這裡是升序,若要降序,只需把a和b位置互換
int main()
{
	long long int n,m;
	long long int cnt=0,sum=0,mnum=0;
	scanf("%lld %lld",&n,&m);
	for(long long int i=0;i<n;i++)
	{
		scanf("%lld",&a[i]);sum=sum+a[i]; //輸入順便求下塊數總和
	}
	qsort(a,n,sizeof(long long int),comp); //快排 需要資料 陣列a,陣列a的長度,陣列a資料型別的大小,以及comp返回的值來判斷是升序還是降序。
	for(long long int i=0;i<n-1;i++) if(a[i]>mnum)mnum++; //計算出最高層數
	cnt=n-1; //根據規律直接得出前n-1列保留的塊數
	if(a[n-1]-mnum>1) //判斷第n列情況
	cnt+=(a[n-1]-mnum);
	else
	cnt++;
	printf("%lld",sum-cnt);
	return 0;
}

C Vasya and Book
Vasya is reading a e-book. The file of the book consists of nn pages, numbered from 11 to nn. The screen is currently displaying the contents of page xx, and Vasya wants to read the page yy. There are two buttons on the book which allow Vasya to scroll dd pages forwards or backwards (but he cannot scroll outside the book). For example, if the book consists of 1010 pages, and d=3, then from the first page Vasya can scroll to the first or to the fourth page by pressing one of the buttons; from the second page — to the first or to the fifth; from the sixth page — to the third or to the ninth; from the eighth — to the fifth or to the tenth.

Help Vasya to calculate the minimum number of times he needs to press a button to move to page yy.
Input
The first line contains one integer tt (1≤t≤10的3次方) — the number of testcases.

Each testcase is denoted by a line containing four integers n, x, y, d (1≤n,d≤10的9次方, 1≤x,y≤n) — the number of pages, the starting page, the desired page, and the number of pages scrolled by pressing one button, respectively
Output
Print one line for each test.

If Vasya can move from page x to page y, print the minimum number of times he needs to press a button to do it. Otherwise print −1.
Example
Input
3
10 4 5 2
5 1 3 4
20 4 19 3
Output
4
-1
5

C題先確定能夠翻到指定頁數的三種情況
1.能從x直接翻到y
2.從x翻到1再翻到y
3.從x翻到n再翻到y
那麼這三種情況怎麼判斷呢,其實就是判斷頁數差的絕對值能否被d整除,那第一種就是abs(x-y)%d,第二種是abs(y-1)%d,第三種是abs(n-y)%d。只要這三種有一種能夠符合,那就是可以翻到指定頁數的。確定能夠翻到指定頁數後,找出翻的最小次數即可。
注意資料 能到1*10的9次方,有些資料要定longlongint。

#include <stdio.h>
#include <math.h>
int min(int x,int y) //找出最小的mind
{
	if(x>y)return y;
	else return x;
}
int main()
{
	int t;
	long long int n,x,y,d;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%lld %lld %lld %lld",&n,&x,&y,&d);
		if(abs(x-y)%d==0||abs(y-1)%d==0||abs(n-y)%d==0) //看三種情況有沒有滿足的
		{
			long long int mind=1e9; //萬一後面翻的次數比較大,如果mind不夠大的話會出現錯誤,因此讓mind初始值足夠大
			if(abs(x-y)%d==0) mind=abs(x-y)/d; //第一種不用多說,直接翻到,翻的次數就是abs(x-y)/d
			if(abs(y-1)%d==0) mind=min(mind,(x+d-1)/d+(y-1)/d); //第二種,先算出翻到1需要的次數,再算出從1到y的次數
			if(abs(n-y)%d==0) mind=min(mind,(n-x+d-1)/d+(n-y)/d); //第三種,先算出從x到n的次數,在算出從n到y的次數
			printf("%lld\n",mind);
		}
		else
		printf("-1\n");
	}
	return 0;
}

D - Vova and Trophies
Vova has won n trophies in different competitions. Each trophy is either golden or silver. The trophies are arranged in a row.

The beauty of the arrangement is the length of the longest subsegment consisting of golden trophies. Vova wants to swap two trophies (not necessarily adjacent ones) to make the arrangement as beautiful as possible — that means, to maximize the length of the longest such subsegment.

Help Vova! Tell him the maximum possible beauty of the arrangement if he is allowed to do at most one swap.
Input
The first line contains one integer n (2≤n≤10的5次方) — the number of trophies.

The second line contains n characters, each of them is either G or S. If the i-th character is G, then the i-th trophy is a golden one, otherwise it’s a silver trophy.

Output
Print the maximum possible length of a subsegment of golden trophies, if Vova is allowed to do at most one swap.

Examples
Input
10
GGGSGGGSGG
Output
7
Input
4
GGGG
Output
4
Input
3
SSS
Output
0

最後一題的題意就是替換一次S或不替換S找出最大G串。
我的思路是先統計S之前G的個數,並在此過程中不斷重新整理G的最大值,在遇到S後把S變成G並重新整理G的最大值,然後繼續讀取G,重新整理G的最大值,再次遇到S後 看從上一次遇到S到這次遇到S過程中讀取的G並加上繼續向後讀取G後的值能否顛覆之前的最大值。。。S多了少了都一個道理。。我說的可能不太清楚,可以看著程式碼自己模擬一下試例,更有助於理解。(t…t感覺講不明白)

#include <stdio.h>
#define MAXN 100001
char s[MAXN];
int max(int x,int y)
{
	if(x>y) return x;
	else return y;
}
int main()
{
	int n;
	scanf("%d",&n);
	scanf("%s",s);
	int maxn=0,cnt=0,k=0,sum=0;
	for(int i=0;i<n;i++)
	{
		if(s[i]=='S') //遇s,把之前統計的G歸零並用mark記錄之前統計G的個數
		{
			cnt=k;k=0;
		}
		else
		{
			k++;sum++; //統計在遇到S之前G的個數
		}
		maxn=max(maxn,cnt+k+1); //找出G串最大值。 其中cnt+k+1需要好好去體會,自己模擬一下。
	}
	if(maxn>sum) maxn--; //因為我上面的cnt+k+1是預設有S要被替換的,所以有+1,假如字串全是G就不能+1,如果+1了maxn比sum還要大1,顯然是錯的,要把多算的一個S減去(比如GGGG)
	printf("%d\n",maxn);
	return 0;
}

我的廢話可能有點多,見諒~~
如有錯誤請評論指正,謝謝了~!!!!