1. 程式人生 > 其它 >黑龍江農墾科技職業學院喜迎寒假多校聯賽2 A,C,F,G,H,I,J題解

黑龍江農墾科技職業學院喜迎寒假多校聯賽2 A,C,F,G,H,I,J題解

技術標籤:演算法指標c++

黑龍江農墾科技職業學院喜迎寒假多校聯賽2 (歡 樂 A K 場) A,C,F,G,H,I,J題解

題目連結
A.
由於該題資料過大 首先就要使用到快讀 不然會超時
快讀模板以及解析(轉載)

如果直接使用暴力每一次累加去做一次if判斷,一定會超時,所以最好把累加就做一個數組,判斷時候就可以直接運用這個陣列去擷取

儲存累加陣列

for(long long i=1;i<=n;i++){
	a=read(); 
	sum[i]=sum[i-1]+a;
	}

有了這個陣列後 我們就可以在裡面直接擷取詢問值,大大減少了程式碼複雜度

判斷及輸出

l=0; r=1;
while(r<=n)
    {
        p=sum[r]-sum[l];
    	if(k==p) Max=max(Max,r-l);
    	if(p>k) l++;
    	if(p<k||r-l<=Max) r++;
	}
	if(Max==0) printf("-1\n");
	else printf("%lld\n",Max);
	return 0;

sum陣列記得開全域性陣列,在全域性數組裡所有值都已經初始化為0且開的範圍也可以更大

.
.
.
.
.

C.
一樣還是要使用快讀不然也會超時
其他的大致和A題思路一樣,所以就直接貼程式碼把

#include<iostream>
using namespace std;
long long a[1000010];
long long pp(){
    char ch;
    while(ch =getchar(), ch < '0' || ch > '9');
    long long res = ch - 48;
    while(ch = getchar(), ch >= '0' && ch <= '9')
    res = res * 10 + ch - 48;
    return res;
}
int main()
{
    long long n,m,sum,p,r,l;
    n=pp(); m=pp();
    for(long long i=1;i<=n;i++)
    {
        p = pp();
        a[i] = a[i-1] + p;
    }
    while(m--){
        r = pp();
        l = pp();
        cout<<a[l] - a[r-1]<<endl;
    }
}

.
.
.
.
.

F.
做F題前 先要了解異或運算是什麼
簡單來說 就是兩個二進位制的每一位進行對比,若相同則新的二進位制的一位為0,不相同則為1
舉個栗子:10和01進行異或運算為11 11和01進行異或運算為10

這題的例子中
例一:10000 輸出:16383 一開始我很疑惑有什麼規律 然後我就百度了一下16838和10000的二進位制數為多少 就發現規律了
16383:11111111111111
10000:10011100010000
發現沒有,位數都相等,所以這題就是找到最大的二進位制位數然後把所有的0換成1就可以了,而最大的二進位制位數就是n
所以發現規律後這題就很簡單了

#include<iostream>
#include<cstring>
using namespace std;
int main(){
    unsigned long long n,k,i=1,er=0,con=0,sum=0;
    scanf("%lld",&n);
    while(n>0)
    {
        n/=2;
        con++;
    }
    sum=1;
    for(int i=1;i<=con;i++)
    {
        sum*=2;
    }
    printf("%lld",sum-1);
}

直接統計n的二進位制有幾位再直接計算就可以了

.
.
.
.
.

G.
這題主要最難的地方就是判斷這句話裡是否有Alan這個字串(主要Alan中間還夾雜空格)
可以用KMP演算法來直接判斷(當字串裡有空格時直接將指標右移就好)
KMP詳解
這題的KMP

for(int i=0;i<k;i++)
		{
			if(a[i]==p[j]) j++;  //如果字元能夠匹配 Alan指標向右移
		    else if(a[i]!=' '&&a[i]!=p[j]) j=0; //如果a[i]等於了空格i也向右移
			if(j==3) break; //如果能夠匹配成功 就判斷這個字串有Alan這個字串
        }  

判斷出了這個字串裡有Alan這個字串後就變得非常簡單了
當判斷出這個字串有Alan後可以直接用for迴圈進行計算有多少個%

if(j==3)
		{
    	   for(int i=0;i<k;i++)
           {
            if(a[i]=='%') sum++;
           }
	    }

.
.
.
.
.

H,I(兩題是一個程式碼)
首先一個使用者有多個數據 所以用結構體儲存這些資料是最好的

struct number{
    string id;
    string mm;
    string ph;
    string sex;
    int p;//用來儲存順序
}k[10010];

之後先是一個簡單的輸入進結構體

 for(int i=1;i<=n;i++)
    {
        cin>>k[i].id>>k[i].mm>>k[i].sex>>k[i].ph;
        k[i].p=i;   //p用來儲存順序
    }

最最最重要的就是這裡面的排序了!!!!!搞了我好久好久好久
先在主函式裡寫好

sort(k+1,k+1+n,cmp);

結構體排序!!!

int cmp(number a,number b)
{
	if(a.id.size()!=b.id.size()) return a.id.size()<b.id.size();//如果兩個ID長度不等就可以直接比出來
	else{
		if(a.id==b.id) return a.p<b.p;  //如果兩個ID相等就比較輸入順序
		else if(a.id!=b.id) return a.id<b.id; //相等就比較兩個ID大小
		else return a.p>b.p;
	}
}

然後直接在主函式裡輸出結構體就完事了!

for(int i=1;i<=n;i++)
    {
        cout<<k[i].id<<' '<<k[i].mm<<' '<<k[i].sex<<' '<<k[i].ph<<endl;
    }

.
.
.
.
.
J.
這題就沒啥了吧
簡簡單單的簽到題找最小值下標而已而已

#include<iostream>
using namespace std;
int main()
{
    int n;
    int min=100,l=1;
    scanf("%d",&n);
    int a[10010];
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        if(min>a[i])
        {
            l=i;
            min=a[i];
        }
    }
    printf("%d",l);
     
 }