2019年湘潭大學程序設計競賽(重現賽)部分題解(A、B、C、D、F)

2019年湘潭大學程序設計競賽(重現賽)

由於本人水平比較菜,只做出了5個,剩下的不太會了。寫簡單題的題解主要是給本校學弟學妹學習學習的。

A、B水題就不解釋了;

代碼比較醜,輕噴

A:A本來是想寫一個結構題排下序的,後來發現重載那裏比較難寫,就換了下面這一種

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,p,s;
int n1,p1,s1;
struct node
{
	int id,x,y,z;
}a[3];
int main()
{
	for(int i=1;i<=2;i++) 
	{
		scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
		a[i].id=i;
	}
	if(a[1].x<a[2].x)
	{
		printf("2\n");
		return 0;
	}
	if(a[1].x>a[2].x)
	{
		printf("1\n");
		return 0;
	}
	if(a[1].y<a[2].y) 
	{
		printf("1\n");
		return 0;
	}
	if(a[1].y>a[2].y)
	{
		printf("2\n");
		return 0;
	}
	if(a[1].z<a[2].z)
	{
		printf("1\n");
		return 0;
	}
	if(a[1].z>a[2].z)
	{
		printf("2\n");
		return 0;
	}
	printf("God\n");
	return 0;
}

B:

#include <bits/stdc++.h>
using namespace std;
int main(){
	int t;cin>>t;
	while(t--)
	{
		int n;int ans=0;
		scanf("%d",&n);
		while(n>1){
			if(n%10!=0)
			{
				ans++;n++;
			}
			while(n%10==0){
				n/=10;
				ans++;
			}
		}
		printf("%d\n",ans);
	}
}

鏈接:https://ac.nowcoder.com/acm/contest/893/C
來源:牛客網
 

題目描述

已知整數a,a3a,a3除192的餘數是1。求區間[L,R]之間滿足條件的a的累加和是多少?

輸入描述:

第一行是一個整數T(1≤T≤10000)T(1≤T≤10000),表示樣例的個數。
每個樣例包含兩個整數L,R,1≤L≤R≤109L,R,1≤L≤R≤109。

輸出描述:

每行輸出一個樣例的結果。

示例1

輸入

複製

1
1 10

輸出

複製

1

C題打表找規律,還不會打表的看我代碼的註釋部分。

至於官方解法,不知道怎麼證的。

可以看看

然後還有一個知識點。如果是求(L,R);我們可以求這個(0,R)-(0,L-1)代替(L,R)。好好想想~

還有人找到規律不知道怎麼寫的嗎?

1,193,385,577.等差數都爲192.

1,192*1+1,192*2+1,192*3+1......以此類推(等差數列通項)。

先不考慮1,都減一個1.(待會加回來就可以了 加個(L-R+1))

0,192*1,192*2,192*3;

那麼只需要統計區間內192的個數*192(前面已經說了(0,R)-(0,L-1)代替(L,R))

這裏還有一個知識點。若R/192=num,那麼num就是0到R區間內包含192的個數(可以自己去證明幾個數玩玩)

 

那麼求出num了,答案就是num*(num+1)/2*192+(L-R+1).(num*(num+1)/2是等差數列求和,上了大學,高中知識快忘了吧,快去百度等差數列怎麼求和的)

數列就變成了

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=1e3+10;
const ll inf=1e9;
ll sum[N*40];
int ls[N*40],rs[N*40];
int cnt=0,rt;
/*void init()
{
	for(ll i=1;i<=1e3;i++)
	{
		if((i*i*i)%192==1)
		{
			printf("i:%lld\n",i);
		}
	}
}*/
int main()
{
	int t;
	//init();
	cin>>t;
	while(t--)
	{
		ll l,r;
		scanf("%lld%lld",&l,&r);
		ll n1=0,n2=0;
		if(l>=2) n1=(l-2)/192;
		if(r>=1)	n2=(r-1)/192;
		//printf("n1:%lld\n",n1);
		//printf("n2:%lld\n",n2);
		ll a1=n1*(n1+1)*192/2;
		ll a2=n2*(n2+1)*192/2;
		//printf("a2:%lld a1:%lld\n",a2,a1);
		ll ans=a2-a1+n2-n1;
		if(l==1) ans++;
		printf("%lld\n",ans);
	}
}

下面是許老師的代碼,多簡潔

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll gao(ll n)
{
    int m=n/192;
    if(n%192)
        m++;
    return 1ll*(1+192*(m-1)+1)*m/2;
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int l,r;
        cin>>l>>r;
        ll ans=gao(r);
        ans-=gao(l-1);
        cout<<ans<<endl;
    }
}

鏈接:https://ac.nowcoder.com/acm/contest/893/D
來源:牛客網
 

有n堆石子排成一排,第i堆石子有aiai個石子。
每次,你可以選擇任意相鄰的兩堆石子進行合併,合併後的石子數量爲兩堆石子的和,消耗的體力等價於兩堆石子中石子數少的那個。
請問,將所有的石子合併成一堆,你所消耗的體力最小是多少?

輸入描述:

第一行是一個整數T(1≤T≤20)T(1≤T≤20),表示樣例的個數。
每個樣例的第一行是一個整數n(1≤n≤10000)n(1≤n≤10000),表示石子堆的數量。
第二行是n個整數ai(1≤ai≤109)ai(1≤ai≤109)

輸出描述:

每行輸出一個樣例的結果。

示例1

輸入

複製

2
2
1 2
1
1

輸出

複製

1
0

說明

巨大的輸入,請使用C風格的輸入。

感覺題解講的很清楚了。管你是不是選擇相鄰的。我永遠從最大的那一堆跟它附近的堆合併。最大堆合併一個堆後還是最大的堆。那麼代價就不會加上最大堆的值。

所以我的做法是排個序,從1加n-1就可以了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e4+10;
ll a[N];
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n;
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
		{
			ll x;
			scanf("%lld",&a[i]);
		}
		ll ans=0;
		sort(a+1,a+1+n);
		for(int i=1;i<=n-1;i++) ans+=a[i];
		printf("%lld\n",ans);
	}
}

鏈接:https://ac.nowcoder.com/acm/contest/893/F
來源:牛客網
 

題目描述

你有一個長度爲 n 的 01 串S,你可以執行最多 m 次操作。
對於每次操作,你可以選擇一個位置 i 滿足 1≤i≤n1≤i≤n,翻轉這一位的值,0變成1,1變成0。
定義一個 01 串的價值爲其中最長連續0的個數和最長連續1的個數的較大值,求S在經過最多m次操作後的最大價值。

輸入描述:

* 第一行一個整數 T ,表示接下來有 T 個樣例。
* 首先輸入n,m,表示S串的長度n和操作次數m,其中1≤n≤1000001≤n≤100000,0≤m≤10000≤m≤1000;
* 接下來輸入一個長度爲n的字符串S。

輸出描述:

一個整數,表示題面上描述的最大價值。

示例1

輸入

複製

2
5 1
00101
2 1
01

輸出

複製

4
2

說明

第一個串翻轉第三個位置,00001的價值爲4;第二個串翻轉第一個位置,11的價值爲2。

F題我的做法不太正確哈,我是純暴力。從每一個點出發,要麼向左延伸,要麼向右延伸,求最大值。時間複雜度:O(1e8);

正確做法請看官方題解:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+10;
char s[N];
int t,a[N],n,m;
struct node
{
	int x,y;
}b[N];
int call(int id,int m)
{
	int pre=a[id];
	int num=1;
	int l=id-1,r=id+1;
	while(m&&l>=1)
	{
		if(a[l]!=pre)m--;
		num++;
		l--;
	}
	while(l>=1&&a[l]==pre)l--,num++;
	while(r<=n&&a[r]==pre) r++,num++;
	return num;
}
int calr(int id,int m)
{
	int pre=a[id];
	int num=1;
	int l=id-1,r=id+1;
	while(m&&r<=n)
	{
		if(a[r]!=pre)m--;
		num++;
		r++;
	}
	while(l>=1&&a[l]==pre)l--,num++;
	while(r<=n&&a[r]==pre) r++,num++;
	return num;
}
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		scanf("%d%d",&n,&m);
		scanf("%s",s+1);
		for(int i=1;i<=n;i++) a[i]=s[i]-'0';
		int ans=0;
		for(int i=1;i<=n;i++)
		{
			int pre=a[i];
			int num=0;
			int a1=call(i,m);
			int a2=calr(i,m);
			num=max(a1,a2);
			ans=max(ans,num);
		}
		printf("%d\n",ans);
	}
}
/*
100

14 6
11110000001111
100
12 1
100001110111
15 1
000100001110111
*/

再貼一下正確做法的代碼,來自hsx

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int pref[105000];
 
int main(){
    int t;
    cin>>t;
    while(t--){
        int n,m;
        cin>>n>>m;
        string s;
        cin>>s;
         
        for(int i=0;i<n;i++){
            if(s[i]=='1')   pref[i+1]=pref[i]+1;//統計1的個數 
            else pref[i+1]=pref[i];
        }
         
        int ans=0;
        for(int i=1;i<=n;i++){//這樣也闊以咯 
            int l=i;
            int r=n;
            while(l<=r){
                int mid=(l+r)/2;
                if(pref[mid]-pref[i-1] <= m){
                    ans=max(ans,mid-i+1);
                    l=mid+1;
                }
                else r=mid-1;
            }
        }
         
        for(int i=1;i<=n;i++){
            int l=i;
            int r=n;
            while(l<=r){
                int mid=(l+r)/2;
                if((mid-i+1) - (pref[mid]-pref[i-1]) <= m){//0的個數 
                    ans=max(ans,mid-i+1);
                    l=mid+1;
                }
                else r=mid-1;
            }
        }
        printf("%d\n",ans);
    }
     
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章