浙江农林大学蓝桥杯程序设计竞赛校选拔赛(补题)

前言:
第一场团队赛,和队友没配合好,成绩不太理想。应该几个人开一道的,都管自己想了。想法应该汇总一下,每个人都差一点点…

A

思路:
签到题,队友理解题意理解错了WA了好几发。我一发A了。。。。

1.小于k的增加到它可以增加的最多数量
2.大于等于h的不变
3.最后有一次增加h的机会,总数ans加个k就ok了

AC代码
:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e6+5;
//floor(2.5) = 2	
ll a[N];
ll n,k,h;
ll ans=0;
int main()
{
	cin>>n>>k>>h;
	for(ll i=1;i<=n;i++) 
	{
		scanf("%lld",&a[i]);
	}
	for(ll i=1;i<=n;i++)
	{
		if(a[i]<k)
		{
			ll t;
		if(h!=0)  t=(k-a[i])/h;
		a[i]=a[i]+h*t; 
		}
	}
	for(ll i=1;i<=n;i++)
	{
		ans+=a[i];
	}
	ans+=h;
	printf("%lld\n",ans);
	return 0;
}

H

签到题,按题意模拟即可
队友一A
AC代码:

#include<cstdio>


char zimu;
int map[8][8];
int  main()
{
    int t;
    scanf("%d",&t);
    map[1][1]=1;
    while(t--)
    {
    	int x=1,y=1;
        int n;
        scanf("%d",&n);
        int i=1;
        for(i=2;i<=n*n;i++)
        {
            scanf(" %c",&zimu);
            if(zimu=='s')
                x+=1;
            if(zimu=='w')
                x-=1;
            if(zimu=='a')
                y-=1;
            if(zimu=='d')
                y+=1;
            map[x][y]=i;
        }
        for(i=1;i<=n;i++)
        {  
            for(int j=1;j<=n;j++)
            {
             //   if(j!=1)
                //    printf(" ");
                printf("%d ",map[i][j]);
            }
            printf("\n");
        }  
        printf("\n");
    }
}

F

也是签到题
一开始想多了,想找到最优解,一下子找出来。。最后老老实实暴力。。。

思路:
先把每个数从大到小排序,然后和原来的数组比较,如果有一个不一样,说明那两个数就是需要交换的数,然后在原来的数组从后往前找,找到了就退出,然后交换,输出即可。

AC代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1010;
char s[N];
ll a[N];
int t;
int l;
int g[N];
void get()
{
	for(int i=1;i<=l;i++)
	{
		a[i]=s[i]-'0';
		g[i]=a[i];
	}
}
bool cmp(int a,int b)
{
	return a>b;
}
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>s+1;
		 l=strlen(s+1);
		 get();
		 int res=-1;
		 int res2=0x3f3f3f3f;
		 int maxi=0;
		 int mini=0;
		 int last1=0;
		 int last2=0;
		 sort(g+1,g+1+l,cmp);
		 for(int i=1;i<=l;i++)
		 {
		 	if(a[i]>=res)
		 	{
		 		res=a[i];
		 		maxi=i;
			 }
		 }
		 int flag=1;
		 for(int i=1;i<=l-1;i++)
		 {
		 	if(a[i+1]>a[i]) 
		 	{
		 		flag=-1;
		 		break;
			 }
		 }
		if(flag==-1)
		{
		/*	for(int i=1;i<=l;i++)
			{
				printf("%d %d\n",g[i].x,g[i].y);
			} */
			int flag2=0;
			int hh;
		for(int i=1;i<=l;i++)
		{
			if(g[i]!=a[i])
			{
			
				for(int j=l;j>=1;j--)
				{
					if(a[j]==g[i])
					{
						hh=j;
						flag2=-1;
						break;
					}
				}
			}
			if(flag2==-1)
			{
				int k=a[i];
				a[i]=a[hh];
				a[hh]=k;
				break;
			}
		}
		
		}
		 for(int i=1;i<=l;i++)
		 {
		 	printf("%d",a[i]);
		 }
		 printf("\n");		 
	}
	return 0;	
}
 

J

思路:
数据范围很小,模拟即可,要细心。

模拟每一次可以插入的位置,然后一直消到不能消为止。

AC代码

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n,k,x;
		int a[200];
		cin>>n>>k>>x;
		for(int i=0;i<n;i++)
		{
			cin>>a[i];
		}
		int  maxn=0;
		for(int i=0;i<n;i++)
		{
			int sum=0;
			if(a[i]==x)
			{
				int l=i,r=i,cnt=0;
				while(l>=0&&a[l]==x) cnt++,l--;
				while(r<n&&a[r]==x) cnt++,r++;
				if(cnt>=3)
				{
					sum=sum+cnt;//去掉的数
					while(l>=0&&r<n)
					{
						int cny=0;
						if(l<0||r>=n) break;
						int xl=a[l],xr=a[r];
						if(xl!=xr) break;
						while(l>=0&&a[l]==xr) cny++,l--;
						while(r<n&&a[r]==xl) cny++,r++;
						if(cny>=3) sum+=cny;
						else break;
					}
				}
			}
			maxn=max(maxn,sum);
		}
		if(maxn==0) cout<<0<<endl;
		else cout<<maxn-1<<endl;
	}
	return 0;
}

G

思路:结论题。列几项,找一下规律。

在这里插入图片描述
可以发现,要翻倍的时候,翻倍/2的值,是一个等比数列的求和。
然后第一项是k,等比为2。 然后要让它分数最小,就让它翻倍的时候断开,让他错,然后找到最后一个对的翻倍点,加上翻倍点后面对的数量。

小细节:
取余的时候,为了防止出现负数最好 (x+mod)%mod
AC代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll mod=1e9+9;
ll n,m,k,a,b,c,ans;
ll qsm(ll b)
{
	ll a=2;
	ll res=1;
	while(b)
	{
		if(b&1)  res=res*a%mod;
		b>>= 1;
		a=a*a%mod;
	}
	return res;
}

int main()
{
	 while (scanf ("%lld%lld%lld", &n, &m, &k) != EOF)
	 {
	 b=n/k;//有几个断点 
	 a=n-m; //需要错几个点。
	ans=0;
	if(m<k) ans=m;
	else if(a>=b) ans=m;
	else 
	{
		c=b-a;	
	
 	ans = (k*((qsm(c+1) + mod - 2)%mod) %mod + m - c*k) % mod;
		 } 
	printf("%lld\n",ans);	 
		 }
	return 0;
}

E

思路:

当时是想用两个变量记录,标记过的区间的左端点和右端点,但是想了一下如果新的区间和原来区间没有交集就不知道怎么办了。
这里他开了个 一维数组,把区间内所有点都赋值为右端点的下标,很巧妙。学到了
AC代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e6;
int g[N];
int d[N];
int n,m,a,b;

int main()
{
	cin>>n>>m>>a>>b;
	for(int i=m;i>=1;i--)
	{
		int x=(i*a+b)%n+1;
		int y=(i*b+a)%n+1;
		if(x>y) swap(x,y);
		for(int j=x;j<=y;j++)
		{
			if(!d[j])
			{
				d[j]=y;
				g[j]=i;
			}
			else
			{
				j=d[j];
			}
		}
	}
	for(int i=1;i<=n;i++)
	{
		cout<<g[i]<<endl;
	}
	return 0;
}

I

思路:
如果第一个行的a[1][i]是1,那么a[1,i] a[1,i-1] a[1,i+1]都不能为1,
然后用一个cnt记录,不能走的个数。
当每次发生变化的时候 更新这个cnt ,最后根据cnt是否为0判断能否到达。

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int cnt;
int mp[4][N];
int n;

void print()
{
	if(cnt) cout<<"You are the worst friend.\n";
	else cout<<"I'm the worst friend.Please forgive me.\n";
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=2;i++)
	{
		for(int j=1;j<=n;j++)
		{
			scanf("%d",&mp[i][j]);
		}
	}
	for(int i=1;i<=n;i++)
	{
		if(mp[1][i]==1)
		{
			if(mp[2][i]) cnt++;
			if(mp[2][i+1]) cnt++;
			if(mp[2][i-1]) cnt++;
		}
	}
	print();
	int m;
	scanf("%d",&m);
	for(int i=0;i<m;i++)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		mp[a][b]^=1;
		if(mp[a][b])
		{
		    if(mp[a+1][b-1])  cnt++;
            if(mp[a+1][b])  cnt++;
            if(mp[a+1][b+1])  cnt++;
            if(mp[a-1][b-1])  cnt++;
            if(mp[a-1][b])  cnt++;
            if(mp[a-1][b+1])  cnt++;
		} 
		else
		{
			 if(mp[a+1][b-1])  cnt--;
            if(mp[a+1][b])  cnt--;
            if(mp[a+1][b+1])  cnt--;
            if(mp[a-1][b-1])  cnt--;
            if(mp[a-1][b])  cnt--;
            if(mp[a-1][b+1])  cnt--;
		}
		print();
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值