1. 程式人生 > 其它 >AtCoder Beginner Contest 196題解

AtCoder Beginner Contest 196題解

Difference Max

題目大意

輸入四個數\(a,b,c,d\),求\(max([a,b]-[c,d])\)的值,其中\([x,y]\)\(x\)~\(y\)中的任意數。

題解

因為資料範圍很小,所以我們可以用兩個迴圈來列舉這兩個數,再一一比較,求出答案,時間複雜度為\(O((b-a)\cdot(d-c))\)

其實,要想使\([a,b]-[c,d]\)最大,只要使被減數最大,減數最小即可,所以答案為\(b-c\),時間複雜度為\(O(1)\)

程式碼

#include<bits/stdc++.h>//列舉
using namespace std;
int main()
{
	int n1,m1,n2,m2,ans=INT_MIN;
	cin>>n1>>m1>>n2>>m2;
	for(int i=n1;i<=m1;i++)
	{
		for(int j=n2;j<=m2;j++)
	    {
		    ans=max(ans,i-j);
	    }
	}
	cout<<ans;
	return 0;
}
#include<bits/stdc++.h>//數學
using namespace std;
int main()
{
	int a,b,c,d;
	cin>>a>>b>>c>>d;
	cout<<b-c;
    return 0;
} 

Round Down

題目大意

輸入一個實數\(n\),把它的整數部分輸出。

題解

很明顯,任何一個整型變數都無法存下這麼大的一個數,所以我們開一個字串來儲存。

我們是可以不把\(n\)全部讀入的,一旦讀到小數點就退出,否則輸出這個字元。

注意一點,就是如果\(n\)本身是整數怎麼辦?也就是說,讀到換行也要退出。要用scanf才能讀到換行。

程式碼

#include<bits/stdc++.h>
using namespace std;
int main()
{
	char ch;
	while(1)
	{
		scanf("%c",&ch);
		if(ch=='.')break;
		if(ch=='\n')break;
		printf("%c",ch);
	}
	return 0;
}

Doubled

題目大意

輸入一個數\(n\),求從\(1\)$n$中有多少個$k(k%2=0)$位數滿足前$1$\(k/2\)位與\(k/2+1\)~\(k\)位完全一樣。

如:\(123123\)\(2020\)

題解

這道題同樣也不能暴力過,但我們發現一旦確定前\(1\)

$k/2$,後面的$k/2+1$\(k\)也可以確定,所以我們只要列舉前面就可以了。

我們還有滿足前面的數拼起來小於\(n\),只要把這個數複製一下就可以了。

程式碼

int Log=log10(i)+1;//複製程式碼
long long k=i*pow(10,Log)+i;
#include<bits/stdc++.h>//完整程式碼
using namespace std;
int main()
{
	long long n,ans=0;
	scanf("%lld",&n);
	for(long long i=1;;i++)
	{
		long long Log=log10(i)+1;
		if(i*pow(10,Log)+i<=n)
		ans++;
		else
		break;
	}
	printf("%d",ans);
	return 0;
}

Hanjo

題目大意

在一個\(n\cdot m\)的棋盤上擺\(1\cdot 1\)\(1\cdot 2\)\(2\cdot 1\)的磚,把棋盤蓋滿,並且用\(a\)\(2\cdot 1\)的磚\(1\cdot 2\)的磚,\(b\)\(1\cdot 1\)的磚。

如:

題解

這道題資料很小,所以我們可以用DFS過,暴力搜尋每一個位置放什麼,對於每個位置,分三種情況:

  1. 放一個\(1\cdot 1\)的磚(不放\(2\cdot 1\)\(1\cdot 2\)的磚)。
  2. 放一個\(1\cdot 2\)的磚。
  3. 放一個\(2\cdot 1\)的磚。

當然,設 \(f_{i,j}\)代表第\(i,j\)的位置上有沒有磚,如果這個位置放磚,就把 \(f_{i,j}=true\),然後回朔。

關於DFS,設三個引數\(x,y,z,x\)代表搜尋在\(x\)行,\(y\)代表搜尋在\(y\)列,\(z\)代表用了\(z\)\(1\cdot 2\)的磚或\(2\cdot 1\)的磚。

如果\(y=m+1\),即搜尋的列到了邊緣,那麼\(x++,y=1\);,也就是說進入下一行的搜尋。

如果\(z=a\),即\(1\cdot 2\)的磚和\(2\cdot 1\)的磚全用完了,因為題目要求\(2a+b=nm\),所以此時不管搜尋到哪裡,剩下的空位都可以用\(1\cdot 1\)的磚補足,\(ans++;retrurn;\)

如果\(x=n+1\),即搜尋到邊界,並且當前的解不合法,直接\(return;\)

如果 \(f_{x,y}=true\),即這個位置已經放好了,那麼直接搜尋下一格\(dfs(x,y+1,z)\)

如果上面的情況都沒有滿足,那麼直接搜尋。

  1. 放一個\(1\cdot 2\)的磚:滿足\(f_{x,y+1}=0\)並且\(y+1\le m\),然後\(dfs(x,y+2,z+1)\),注意是\(y+2\),因為這個磚只有\(2\)格寬,記得回朔。

  2. 放一個\(2\cdot 1\)的磚:滿足\(f_{x+1,y}=0\)並且\(x+1\le n\),然後\(dfs(x,y+1,z+1)\),注意是\(y+1\),因為這個磚只有\(1\)格寬,記得回朔。

  3. 一個都不放,直接\(dfs(x,y+1,z);\)

程式碼

#include<bits/stdc++.h>
using namespace std;
int n,m,a,b,ans;
bool f[30][30];
void dfs(int x,int y,int z)
{
	if(y==m+1)
	{
		x++;
		y=1;
	}
	if(z==a)
	{
		ans++;  
		return;
	}
	if(x==n+1)
	    return;
	if(f[x][y])
	    dfs(x,y+1,z);
	else
	{
		if(!f[x][y+1]&&y+1<=m)
		{
			f[x][y+1]=true;
		    dfs(x,y+2,z+1);
		    f[x][y+1]=false;
		}
		if(!f[x+1][y]&&x+1<=n)
		{
		    f[x+1][y]=true;
		    dfs(x,y+1,z+1);
		    f[x+1][y]=false;
		}
		dfs(x,y+1,z);
	}
}
int main()
{
	
	scanf("%d%d%d%d",&n,&m,&a,&b);
	dfs(1,1,0);
	cout<<ans;
	return 0;
}