2018西安电子科技大学第十六届“华为杯”大学生程序设计竞赛现场赛部分题解

总体来说,这次校赛打的中规中矩,算是正常发挥吧。过了4题,依靠罚时取得了还不错的成绩。
下面发出一些题的题解(有的参考了其他人的思路)


--------------------------------------------------------------------------------------------------------------------------------
A题

大水题,就不啰嗦了,直接上代码
#include<cstdio>
#include<cstring>
using namespace std;
char word[25];
int main()
{
    int t;
	scanf("%d",&t);
	for(int i=0;i<t;i++)
	{
		scanf("%s",word);
		if(strcmp(word,"zero")==0)
			printf("ling\n");
		else if(strcmp(word,"one")==0)
			printf("yi\n");
		else if(strcmp(word,"two")==0)
			printf("er\n");
		else if(strcmp(word,"three")==0)
			printf("san\n");
		else if(strcmp(word,"four")==0)
			printf("si\n");
		else if(strcmp(word,"five")==0)
			printf("wu\n");
		else if(strcmp(word,"six")==0)
			printf("liu\n");
		else if(strcmp(word,"seven")==0)
			printf("qi\n");
		else if(strcmp(word,"eight")==0)
			printf("ba\n");
		else if(strcmp(word,"nine")==0)
			printf("jiu\n");
		else if(strcmp(word,"ten")==0)
			printf("shi\n");
	}
	return 0;
}

B题
直接暴力找就可以了,复杂度O(mn)
 
 
#include<cstdio>
#include<vector>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
char zimu[110];
char dian[1010][20];
int flag[30];
int main()
{
	int n;
	while(scanf("%s",zimu)!=EOF)
	{
		memset(flag,0,sizeof(flag));
		int len=strlen(zimu);
		for(int i=0;i<len;i++)
		flag[zimu[i]-'a']=1;
		scanf("%d",&n);
		for(int i=0;i<n;i++)
		scanf("%s",dian[i]);
		int maxn=0;
		for(int i=0;i<n;i++)
		{
			int f=1;
			int len1=strlen(dian[i]);
			for(int j=0;j<len1;j++)
			{
				if(flag[dian[i][j]-'a']!=1)
				f=0;
			}
			if(f==1)
			maxn=max(len1,maxn);
		}
		printf("%d\n",maxn);
	}
	return 0;
}

C题

不能暴力做,会超时(我最开始头铁T了2发)。找规律,如1,2,3,4,5会发现1出现4次,2出现3次,3出现2次,4出现1次。所以先排个序,每个数出现的次数就固定了。 
#include<cstdio>
#include<vector>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<queue>
int a[2600];
int res[3200000];
int num[2600];
using namespace std;
bool cmp(int a1,int a2)
{
  return a1>a2;
}
int main()
{
 int n,k,t;
 scanf("%d",&t);
 for(int i=0;i<t;i++)
 {
  int u=0;
  scanf("%d%d",&n,&k);
  for(int j=0;j<n;j++)
  {
    scanf("%d",&a[j]);
     }
  sort(a,a+n);
  for(int j=0;j<n;j++)
  {
     num[j]=n-j-1;
     }
     for(int j=0;j<n;j++)
     {
      while(num[j])
      {
       num[j]--;
       res[u++]=a[j];
      }
     }
     printf("%d\n",res[n*(n-1)/2-k]);
  //sort(res,res+u,cmp);
  //printf("%d\n",res[k-1]);
 }
 return 0;
}

D题
我还是找规律,其实规律也很简单,就是sum/n(窝太弱了,规律不会证。。。)
#include<cstdio>
#include<vector>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<queue>
int a[1010];
using namespace std;
int main()
{
	int n,t;
	scanf("%d",&t);
	for(int i=0;i<t;i++)
	{
		int sum;
		sum=0;
		scanf("%d",&n);
		for(int j=0;j<n;j++)
		{
		  scanf("%d",&a[j]);
		  sum+=a[j];
	    }
		sort(a,a+n);
		printf("%d\n",sum/n);
	}
	return 0;
}

E题
一道dp题,看了赛后给的思路才会做(窝太弱了。。。)。dp[i][j],i表示以i结尾,j表示模为j。线性复杂度,详见代码。(不要忘了开long long)
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int dp[1000010][3];
char s[1000010];
int main()
{
    while(scanf("%s",s)!=EOF)
    {
    	long long int sum=0;
    	if(s[0]=='0')
    	{
           dp[0][0]=1;
           dp[0][1]=0;
           dp[0][2]=0;
    	}
    	else if(s[0]=='1')
    	{
           dp[0][0]=0;
           dp[0][1]=1;
           dp[0][2]=0;
    	}
    	sum+=dp[0][0];
    	int len=strlen(s);
    	for(int i=1;i<len;i++)
    	{
    		if(s[i]=='0')
    		{
    		   dp[i][0]=dp[i-1][0]+1;
    		   dp[i][1]=dp[i-1][2];
    		   dp[i][2]=dp[i-1][1];
    		}
    		else if(s[i]=='1')
    		{
    		   dp[i][0]=dp[i-1][1];
    		   dp[i][1]=dp[i-1][0]+1;
    		   dp[i][2]=dp[i-1][2];	
    		}
            sum+=dp[i][0];
    	}
    	printf("%lld\n",sum);
    }
	return 0;
}

F题
思路参考了 https://blog.csdn.net/qq_40772738/article/details/80034829,用set维护啊,不知道set自带排序,导致比赛时一直TLE。
#include<cstdio>
#include<set>
#include<map>
#include<cstring>
using namespace std;
typedef pair<int,int> P;
int a[50010];
int b[50010];
int ok[50010];
int main()
{
	int n,m,q;
	set<P> s;
	while(scanf("%d%d%d",&n,&m,&q)!=EOF)
	{
         int ans=0;
         memset(b,0,sizeof(b));
         memset(ok,0,sizeof(ok));
         s.clear();
         for(int i=0;i<q;i++)
         {
             scanf("%d",&a[i]);
             b[a[i]]++;
         }
         for(int i=0;i<q;i++)
         {
         	if(!ok[a[i]])
            {
            	if(s.size()<n)
            	{
            	   s.insert(P(b[a[i]],a[i]));
            	   ok[a[i]]=1;
            	   ans++;
            	}
            	else
            	{
                    ans++;
                    set<P>::iterator it;
                    it=s.begin();
                    int tem=(*it).second;
                    s.erase(it);
                    ok[tem]=0;
                    s.insert(P(b[a[i]],a[i]));
                    ok[a[i]]=1;
            	}
            }
            else
            {
                s.erase(P(b[a[i]],a[i]));
                b[a[i]]--;
                s.insert(P(b[a[i]],a[i]));
            }
         }
         printf("%d\n",ans); 
	}
	return 0;
}

G题
很坑,网络赛题的升级版。当时用搜索做的,这次过不了。标程给的dp,我觉得用素数筛更好一些,再加上找规律。就等于n的所有(素数-1)的和。这道题当时没做出来有些可惜~~
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int MAXN = 1000000;
int prime[MAXN + 1];
void getPrime()
{
    memset(prime, 0, sizeof(prime));
    for (int i = 2; i <= MAXN; i++)
    {
        if (!prime[i])
        {
            prime[++prime[0]] = i;
        }
        for (int j = 1; j <= prime[0] && prime[j] <= MAXN / i; j++)
        {
            prime[prime[j] * i] = 1;
            if (i % prime[j] == 0)
            {
                break;
            }
        }
    }
    return ;
}

long long factor[100][2];
int fatCnt;
int getFactors(long long x)
{
    fatCnt = 0;
    long long tmp = x;
    for (int i = 1; prime[i] <= tmp / prime[i]; i++)
    {
        factor[fatCnt][1] = 0;
        if (tmp % prime[i] == 0)
        {
            factor[fatCnt][0] = prime[i];
            while (tmp % prime[i] == 0)
            {
                factor[fatCnt][1]++;
                tmp /= prime[i];
            }
            fatCnt++;
        }
    }
    if (tmp != 1)
    {
        factor[fatCnt][0] = tmp;
        factor[fatCnt++][1] = 1;
    }
    return fatCnt;
}
int main()
{
    int t,n;
    scanf("%d",&t);
    getPrime();
    while(t--)
    {
    	int sum=0;
    	scanf("%d",&n);
    	int len=getFactors(n);
        for(int i=0;i<len;i++)
        {
            sum+=(factor[i][0]-1)*factor[i][1];
        }
        printf("%d\n",sum);
    }
    return 0;
}

H,I,J就不写了,本身过的人也不多(比较难)~
总结一下就是不会的东西还很多,思路受阻。明年再努力吧~

猜你喜欢

转载自blog.csdn.net/star_moon0309/article/details/80103687
今日推荐