【紀中2020.2.19日】模擬賽題解

目錄:

T1:找路
T2:家庭作業
T3:算法學習
T4:友好數對

正題:

T1:找路

題目描述

Mirko 剛開始學車,因此他還不會在一個很狹窄的地方掉頭,所以他想找一個不需要掉頭的地方學車。Mirko馬上發現他想找的地方必須沒有死衚衕,因爲死衚衕是不可能出來的,除非掉頭(假設Mirko也不會倒車)。現在,你需要寫一個程序,來分析一個地方的地圖,研究是否這個地方適合Mirko練習開車。

這張地圖是包含R*C個單元格的,單元格中的“X”代表一個建築物,單元格中的“.”代表路面。從一個路面單元格,Mirko可以向旁邊上下左右四個方向的單元格開去,只要開過去的地方同樣也是路面。

最後,我們要得出這個地圖是否包含死衚衕,假如從任意一個路面單元格出發,沿着任何一個可以行駛的方向,我們可以不用掉頭就能返回到出發點,那麼這個地圖就是沒有死衚衕的。

輸入

第一行包括兩個整數R和C(3<=R,C<=10),表示這個地圖的大小。

接下來R行,每行有C個字符,每個字符可能是“X”和“.”。地圖中至少有兩個路面單元格,並且所有的路面都是相連的(相互可達的)。

輸出

輸出只有一行,輸出0表示這個地圖沒有死衚衕,輸出1表示這個地圖存在死衚衕。

在這裏插入圖片描述

分析:

這道題很簡單。
就是遍歷整個地圖,如果有一個點四周是‘.’,就計數。
如果有<2個這樣的點,就說明沒有死衚衕

CODE:

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
using namespace std;
char a[12][12];
int m,n;
bool f=true;
int main()
{
	freopen("okret.in","r",stdin);
	freopen("okret.out","w",stdout);
	memset(a,'X',sizeof(a));
	scanf("%d%d",&m,&n);
	for (int i=1;i<=m;i++)
	{
		for (int j=1;j<=n;j++)
		{
			scanf(" %c",&a[i][j]);  //讀入
		}
	}
	for (int i=1;i<=m;i++)
	{
		for (int j=1;j<=n;j++)
		{
			int t=0;  //計數器
			if (a[i][j]=='X') continue;  //不是'.'
			if (a[i-1][j]=='.') t++;
			if (a[i][j-1]=='.') t++;
			if (a[i+1][j]=='.') t++; //判斷上下左右
			if (a[i][j+1]=='.') t++;
			if (t<2)  //小於2個
			{
				f=false;
			}
		}
	}
	if (f) printf("0");  //沒有死衚衕
	else printf("1"); //有死衚衕
}

T2:家庭作業

題目描述

Mirko最近收到了一個家庭作業,作業的任務是計算兩個數A和B的最大公約數。由於這兩個數太大了,我們給出了N個數,他們的乘積是A,給出M個數,他們的乘積是B。

Mirko想要驗算自己的答案,所以他想找你寫一個程序來解決這個問題。如果這個最大公約數超過了9位數,那麼只需要輸出最後9位就可以了。

輸入

第一行包含一個正整數N,範圍是1到1000。第二行是N個用空格隔開的正整數(小於10億),他們的乘積是A。第三行包含一個正整數M,範圍是1到1000。第四行是M個用空格隔開的正整數(小於10億),他們的乘積是B。

輸出

輸出有且只有一行,表示A和B的最大公約數,如果結果超過了9位數,輸出最後9位數就可以了。
在這裏插入圖片描述

分析:

這道題要求最大公約數
如果最大公約數>題目要求,做個標記,最後判斷一下,printf("%09ld",ans),就是輸出後9位

#include<cmath>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long LL;
int n,m;
LL k,ans=1,a[1001],x,f;
int euclid(int y,int x)
{
	if(x==0) return y;  //求最大公約數函數
	return euclid(x,y%x);
}
int main(){
	//freopen("zadaca.in","r",stdin);
	//freopen("zadaca.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++) 
	scanf("%lld",&a[i]);
	scanf("%d",&m);
	for(int i=1; i<=m; i++)
    {
        scanf("%lld",&x);
        for(int j=1; j<=n; j++)
        {
            k=euclid(a[j],x);  //找兩個數列中的最大公約數
            if(ans*k>=1000000000)  
                f=1;  //標記
            ans=ans*k%1000000000;  //取後9位
            a[j]/=k;
            x/=k;
        }
    }
    if(f==1) //有標記
        printf("%09ld",ans);  //輸出後9位
    else
        printf("%lld",ans);
}

T3:算法學習

題目描述

自從學習了動態規劃後,Famer KXP對動態規劃的熱愛便一發不可收拾,每天都想找點題做,一天,他找到了一道題,但是不會做,於是,他找到了你。題目如下:
給出N個無序不重複的數,再有M個詢問,每次詢問一個數是否在那N個數中,若在,則ans增加2^K,K爲該數在原數列中的位置。
由於ans過大,所以只要求你輸出ans mod 10^9+7。

輸入

第一行,兩個數N,M,第二行N個數,第三行M個數。

輸出

輸出最終答案。

樣例輸入

5 5
1 3 4 6 5
1 8 1 3 6

樣例輸出

24

分析:

很多做法。
一種正解爲二分查找+快速冪
兩個函數打好後帶到主函數就ok。

CODE:

#include <iostream>
#include <cstdio>
using namespace std;
long long k,n,m,ans,z,a[100001],b[100001],c[100001];
void fast(long long l,long long r)
{   //快排
    if (l>=r) return;
    int i=l,j=r;
    long long mid=a[(l+r)/2];
    do
    {
        while(a[i]<mid) i++;
        while(a[j]>mid) j--;
        if(i<=j)
        {
            a[0]=a[i];a[i]=a[j];a[j]=a[0];
            b[0]=b[i];b[i]=b[j];b[j]=b[0];
            i++;j--;
        }
    }
    while(i<=j);
    fast(l,j);
    fast(i,r);
}
int search_(long long x,long long y)
{  //二分查找
    int m=x+(y-x)/2;
    if(a[m]==k)
        return m;
    if(a[m]>k)
        return search_(x,m-1);
    if(a[m]<k)
        return search_(m+1,y);
}
int main()
{   
    freopen("sfxx.in","r",stdin);
    freopen("sfxx.out","w",stdout);
    cin>>n>>m;
    b[0]=1; 
    for(int i=1; i<=n; i++)
    {
        cin>>a[i];
        b[i]=(b[i-1]*2)%1000000007; 
    }
    fast(1,n);
    for(int i=1; i<=m; i++)
    {
        cin>>k;
        if((k>=a[1])&&(k<=a[n]))
        {
            ans=(ans+b[search_(1,n)])%1000000007;  //帶入再%
        }
    }
    cout<<ans<<endl;
}

T4:友好數對

題目描述

 在順利完成家庭作業以後,Mirko感到非常的厭倦。所以,他列出了N個數,這些數中有些數對他是喜歡的,有些數對他是不喜歡的。

他喜歡的數對叫做友好數對,如果兩個數至少有一個相同的數字(不要求在相同的位置),那麼這兩個數就是友好數對。請幫助Mirko在這N個數找出有多少友好數對。

輸入

第一行一個正整數N(1<=N<=1000000)。

接下來N行,每行一個正整數,範圍在1到1018之間。N個數中任意兩個數都是不同的。

輸出

只有一行一個整數,表示友好數對的個數。

在這裏插入圖片描述

分析:

剛看這道題,感覺不可做
聽完我們學校一位dalao的講解後,得:
先把輸入的數在二進制下判斷兩個數有沒有相同一位都爲1,也就是都有一個相同的數,然後標記當前位,最後判斷合法,累加答案。

CODE:

#include<cmath>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long LL;
LL ans,b[10001];
LL i,n,t,s,j,k,x;
int main(){
	//freopen("kompici.in","r",stdin);
	//freopen("kompici.out","w",stdout);
	scanf("%lld",&n);
	for(i=1;i<=n;i++)
	{
		t=0;s=0;
		scanf("%lld",&x);
		while(x>0)
		{
			t=x%10;
			x=x/10;
			s=s|(1<<t);  //或運算+位運算判斷哪一位相同
		}
		b[s]++;  //相同的位標記
	}
	for(i=1;i<=1023;i++)
	{
		if(b[i]==0) continue;  //沒有標記
		for(j=1;j<=1023;j++)
		{
			if((i&j)==0/*沒有一位相同*/||b[j]==0||i==j) continue;  //都是不合法條件
			ans=ans+b[i]*b[j]; 
		}
		ans=ans+b[i]*(b[i]-1);
	}
	ans=ans/2;  //最後 div 2
	cout<<ans;
	
return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章