2017蓝桥杯C++B组省赛

1.购物单

思路:代码比计算器算更快

输入:

180.90       88
10.25        65
56.14        90
104.65       90
100.30       88
297.15       50
26.75        65
130.62       50
240.28       58
270.62       80
115.87       88
247.34       95
73.21        90
101.00       50
79.54        50
278.44       70
199.26       50
12.97        90
166.30       78
125.50       58
84.98        90
113.35       68
166.57       50
42.56        90
81.90        95
131.78       80
255.89       78
109.17       90
146.69       68
139.33       65
141.16       78
154.74       80
59.42        80
85.44        68
293.70       88
261.79       65
11.30        88
268.27       58
128.29       88
251.03       80
208.39       75
128.88       75
62.06        90
225.87       75
12.89        75
34.28        75
62.16        58
129.12       50
218.37       50
289.69       80

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
#include<vector>
using namespace std;
int main()
{
	int n=50;
	double a,b,ans;
	while(n--)
	{
		cin>>a>>b;
		ans+=a*(b/100.0);
	}
	cout<<ans;
	return 0;
}

答案:5136.86 -> 5200

 

2.等差素数列

思路:先打个素数表,然后用素数枚举数列的前两项,得出公差之后,判断后面八项是否也是素数(这里不小心写成了判断后九项,多算了一项,一直wa,所以要细心

小tips:题目要求最小公差,其实可以枚举公差,和上述方法实质相同,但是感觉思路上稍微清晰一些。

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
#include<vector>
using namespace std;
int prime[1000010];
int isprime[1000010]; 
int main()
{
	int i,j,num=0;
	for(i=0;i<1000000;i++)
		isprime[i]=1;
	for(i=2;i<1000000;i++)
	{
		if(isprime[i])
			prime[num++]=i;
		for(j=0;j<num&&i*prime[j]<=1000000;j++)
		{
			isprime[i*prime[j]]=0;
			if(i%prime[j]==0)
				break;
		}
	}
	int k,d,book;
	for(i=0;i<num;i++)
	{
		for(j=i+1;j<num;j++)
		{
			d=prime[j]-prime[i];
			book=0;
			for(k=2;k<=9;k++)
			{
				if((prime[i]+k*d<1000000)&&isprime[prime[i]+k*d]==1)
					book=0;
				else
				{
					book=1;
					break;
				}
			}
			if(book==0)
			{
				cout<<d<<endl;
				break;
			}
		}
		if(book==0)
			break;
	}
	return 0;
}

答案:210

 

3.承压计算

思路:把每一个电子秤上的示数都计算出来,排序后,用题目中的示数和最小的数做除法,得出换算单位,再乘上最大的数,即为答案

注意:cout输出double时,会自动变成科学计数法,所以这里要用printf

输入:

                             7 
                            5 8 
                           7 8 8 
                          9 2 7 2 
                         8 1 4 9 1 
                        8 1 8 8 4 1 
                       7 9 6 1 4 5 4 
                      5 6 5 5 6 9 5 6 
                     5 5 4 7 9 3 5 5 1 
                    7 5 7 9 7 4 7 3 3 1 
                   4 6 4 5 5 8 8 3 2 4 3 
                  1 1 3 3 1 6 6 5 5 4 4 2 
                 9 9 9 2 1 9 1 9 2 9 5 7 9 
                4 3 3 7 7 9 3 6 1 3 8 8 3 7 
               3 6 8 1 5 3 9 5 8 3 8 1 8 3 3 
              8 3 2 3 3 5 5 8 5 4 2 8 6 7 6 9 
             8 1 8 1 8 4 6 2 2 1 7 9 4 2 3 3 4 
            2 8 4 2 2 9 9 2 8 3 4 9 6 3 9 4 6 9 
           7 9 7 4 9 7 6 6 2 8 9 4 1 8 1 7 2 1 6 
          9 2 8 6 4 2 7 9 5 4 1 2 5 1 7 3 9 8 3 3 
         5 2 1 6 7 9 3 2 8 9 5 5 6 6 6 2 1 8 7 9 9 
        6 7 1 8 8 7 5 3 6 5 4 7 3 4 6 7 8 1 3 2 7 4 
       2 2 6 3 5 3 4 9 2 4 5 7 6 6 3 2 7 2 4 8 5 5 4 
      7 4 4 5 8 3 3 8 1 8 6 3 2 1 6 2 6 4 6 3 8 2 9 6 
     1 2 4 1 3 3 5 3 4 9 6 3 8 6 5 9 1 5 3 2 6 8 8 5 3 
    2 2 7 9 3 3 2 8 6 9 8 4 4 9 5 8 2 6 3 4 8 4 9 3 8 8 
   7 7 7 9 7 5 2 7 9 2 5 1 9 2 6 5 3 9 3 5 7 3 5 4 2 8 9 
  7 7 6 6 8 7 5 5 8 2 4 7 7 4 7 2 6 9 2 1 8 2 9 8 5 7 3 6 
 5 9 4 5 5 7 5 5 6 3 5 3 9 5 8 9 5 4 1 2 6 1 4 3 5 3 2 4 1 

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
#include<vector>
using namespace std;
double a[30][30];
int main()
{
	int i,j;
	for(i=0;i<=28;i++)
		for(j=0;j<=i;j++)
			cin>>a[i][j];
	for(i=0;i<=28;i++)
	{
		for(j=0;j<=i;j++)
		{
			a[i+1][j]+=a[i][j]/2.0;
			a[i+1][j+1]+=a[i][j]/2.0;
		}
	}
	sort(a[29],a[29]+30);
	//for(j=0;j<30;j++)
		//cout<<a[29][j]<<endl;
	double m=2086458231,minn=a[29][0],maxx=a[29][29];
	printf("%f\n",m/minn*maxx);
	
	return 0;
}

答案:72665192664

 

4.方格分割

思路:直接模拟比较复杂,可以利用两部分完全相同这一点进行思维的转换。可以将整个图看作是7*7的待分割格子,两部分完全相同——说明分割后的两部分关于中点(3,3)中心对称,即中点处一定与两部分都相邻。

从中心点开始向四周深搜,相当于切割,同时与它呈中心对称的位置进行反向切割,直到遇到边界为止。由于整个地图是正方形,终点落在四条边时总有一种重复的,所以最后答案➗4。

注意book数组标记为1的时候,和它关于中心对称的点也要标记,这样做是为了保证分割出来的两部分完全相同

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
#include<vector>
using namespace std;
int nextx[4]={-1,1,0,0};
int nexty[4]={0,0,-1,1};
int book[7][7];
int ans;
void dfs(int x,int y)
{
	if(x==0||x==6||y==0||y==6)
	{
		ans++;
		return;
	}
	int nx,ny,i;
	for(i=0;i<4;i++)
	{
		nx=x+nextx[i];
		ny=y+nexty[i];
		if(nx>=0&&nx<=6&&ny>=0&&ny<=6) //必定成立,可不写 
		{
			if(book[nx][ny]==0)
			{
				book[nx][ny]=1;
				book[6-nx][6-ny]=1;   //保证对称,必须写 
				dfs(nx,ny);
				book[nx][ny]=0;
				book[6-nx][6-ny]=0;
			}
		}
	}
	return;
}
int main()
{
	book[3][3]=1;
	dfs(3,3);
	cout<<ans/4<<endl;
	return 0;
}

答案:509

 

7.日期问题

思路:注意日期的简单写法,还需练习

wa点:题目说A、B、C都可以等于零,judge2中忘了判断C大于零,一直wa

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
#include<vector>
using namespace std;
struct node{
	int x,y,z;
};
node ans[20];
int cnt;
bool cmp(node n1,node n2)
{
	if(n1.x==n2.x)
	{
		if(n1.y==n2.y)
			return n1.z<n2.z;
		else
			return n1.y<n2.y;
	}
	else
		return n1.x<n2.x;
}
int judge(int year)
{
	if(year%4==0&&year%100!=0||year%400==0)
		return 1;
	return 0;
}
int day[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
void judge2(int a,int b,int c)
{
	if(c>0&&c<=day[b]+((b==2)?judge(a):0))
	{
		ans[cnt].x=a;
		ans[cnt].y=b;
		ans[cnt].z=c;
		cnt++;
	}	
}
void judge1(int a,int b,int c)
{
	if(a>=60&&b>=1&&b<=12)
		judge2(a+1900,b,c);
	if(a<60&&b>=1&&b<=12)
		judge2(a+2000,b,c);
}
int main()
{
	int a,b,c;
	scanf("%d/%d/%d",&a,&b,&c);
	judge1(a,b,c);
	judge1(c,a,b);
	judge1(c,b,a);
	sort(ans,ans+cnt,cmp);
	if(cnt!=0)
		printf("%04d-%02d-%02d\n",ans[0].x,ans[0].y,ans[0].z);
	for(int i=1;i<cnt;i++)
		if(ans[i].x!=ans[i-1].x||ans[i].y!=ans[i-1].y||ans[i].z!=ans[i-1].z)
			printf("%04d-%02d-%02d\n",ans[i].x,ans[i].y,ans[i].z);
	return 0;
}

 

8.包子凑数

思路:当两个数不互质时,即gcd不等于1,它们不能凑出的数一定是无限的;当两个数互质时,即gcd等于1,它们凑不出的数是有限的,最大为a*b-a-b。

由上可知,这些数之间不互质时可以直接输出INF;

当互质时,就要求出具体的凑不出的数。用一个book数组进行标记,枚举最大范围内所有能凑出的数,标记为1,最后累加所有标记为0的个数,即为答案。

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
#include<vector>
using namespace std;
int main()
{
	int n,i,m,j;
	int a[110],book[10010];
	cin>>n;
	for(i=0;i<n;i++)
	{
		cin>>a[i];
		if(i==0)
			m=a[0];
		m=__gcd(m,a[i]);
		book[a[i]]=1;
	}
	if(m!=1)
		cout<<"INF"<<endl;
	else
	{
		book[0]=1;
		for(i=0;i<n;i++)
			for(j=1;j+a[i]<=10000;j++)
				if(book[j]==1)
					book[j+a[i]]=1;
		int ans=0;
		for(i=0;i<=10000;i++)
			if(book[i]==0)
				ans++;
		cout<<ans<<endl;
	}
	return 0;
}

 

9.分巧克力

思路:二分查找。注意左端点L和右端点R的选取;注意while循环的条件,不要死循环

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
#include<vector>
using namespace std;
int h[100010],w[100010];
int main()
{
	int n,k,i;
	cin>>n>>k;
	int maxx=0;
	for(i=0;i<n;i++)
	{
		cin>>h[i]>>w[i];
		maxx=max(maxx,max(h[i],w[i]));
	}
	int l=1,r=maxx,mid,cnt,ans;
	while(l<=r)
	{
		mid=(l+r)/2;
		cnt=0;
		for(i=0;i<n;i++)
			cnt+=(h[i]/mid)*(w[i]/mid);
		if(cnt<k)
			r=mid-1;
		else
		{
			ans=mid;
			l=mid+1;
		}
	}
	cout<<ans<<endl;
	return 0;
}

 

10.k倍区间

题意:给定一个大小为n的数列,求区间和是k的倍数的区间个数。

思路:求前缀和,如果两个位置的前缀和模k的结果相同,说明这两个前缀和的差是一个k倍的数,即这两个位置之间的数之和一定是k的倍数。

用一个book[i]数组记录模k等于i的前缀和的个数。

每求出一个位置的前缀和,模k之后若等于m,给答案累加book[m],即相当于在本位置之前的模k等于m的位置与本位置构成的区间的个数,然后将book[m]+1。

最后答案要再加上book[0],因为本身就是k的倍数的数,自己就可以构成这个区间。

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
#include<vector>
using namespace std;
int a[100010],book[100010];
int main()
{
	int i,n,k,sum=0;
	long long ans=0;
	cin>>n>>k;
	for(i=0;i<n;i++)
	{
		cin>>a[i];
		sum+=a[i];
		sum%=k;
		ans+=book[sum];
		book[sum]++;
	}
	cout<<ans+book[0]<<endl;
	return 0;
}

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值