2020蓝桥杯C++B组国赛

1.美丽的2

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
#include<vector>
using namespace std;
int main()
{
    int i,j,ans=0;
    for(i=1;i<=2020;i++)
    {
        j=i;
        while(j!=0)
        {
            if(j%10==2)
            {
                ans++;
                break;
            }
            j/=10;
        }
    }
    cout<<ans<<endl;
    
    return 0;
}

答案:563

2.扩散

思路:比赛时忘记了还有负数的情况,可以将整个坐标系向左、下移2020个单位,即给定的4个点的横纵坐标加上2020,然后广搜打标记即可。

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
#include<vector>
#include<queue>
using namespace std;
struct node{
	int x,y,cnt;
};
int book[7000][7000],ans=4;
int nextx[4]={-1,0,0,1};
int nexty[4]={0,1,-1,0};
int main()
{
	queue<node>q;
	node n1,n2;
	n1.x=0+2020,n1.y=0+2020,n1.cnt=0;
	q.push(n1);
	book[n1.x][n1.y]=1;
	n1.x=2020+2020,n1.y=11+2020,n1.cnt=0;
	q.push(n1);
	book[n1.x][n1.y]=1;
	n1.x=11+2020,n1.y=14+2020,n1.cnt=0;
	q.push(n1);
	book[n1.x][n1.y]=1;
	n1.x=2000+2020,n1.y=2000+2020,n1.cnt=0;
	q.push(n1);
	book[n1.x][n1.y]=1;
	while(!q.empty())
	{
		n1=q.front();
		q.pop();
		if(n1.cnt>=2020)
			continue;
		for(int i=0;i<4;i++)
		{
			int nx=n1.x+nextx[i];
			int ny=n1.y+nexty[i];
			if(book[nx][ny]==0)
			{
				book[nx][ny]=1;
				ans++;
				n2.x=nx,n2.y=ny,n2.cnt=n1.cnt+1;
				q.push(n2);
			}
		}
	}
	cout<<ans<<endl;
	
	return 0;
}

答案:20312088

3.阶乘约数

思路:一开始想的用1-n的数字随意组合,看能组出多少种不同的数,但是这样会出现重复的数,而且不太好去掉。

所以想到了分解质因数,记录所有素数的个数,每种素数可以有它的个数+1种选择,即不选、选一个、选两个、...、全选,最后答案为(每种素数个数+1)的乘积。

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
#include<vector>
#include<queue>
using namespace std;
int prime[110];
int isprime[110];
int book[110];
int main()
{
	int i,j,k,num=0;
	long long ans=1;
	for(i=2;i<=100;i++)
	{
		if(isprime[i]==0)
			prime[num++]=i;
		for(j=0;j<num&&i*prime[j]<=100;j++)
		{
			isprime[i*prime[j]]=1;
			if(i%prime[j]==0)
				break;
		}
	}
	
	for(i=2;i<=100;i++)
	{
		j=i;
		for(k=2;k*k<=j;k++)
		{
			while(j%k==0&&isprime[k]==0)
			{
				book[k]++;
				j/=k;
			}
		}
		if(j>1)
			book[j]++;
	}
	for(i=2;i<100;i++)
	{
		if(book[i]!=0)
			ans*=(book[i]+1);
	}
	cout<<ans<<endl;
	
	return 0;
}

答案:39001250856960000

4.本质上升序列

思路:(我觉得我的做法还是挺暴力的,半分钟内肯定能跑出来,毕竟是个填空,而且最主要的是其实我也想不出什么巧妙的算法,能拿分就是最重要的)

用一个set集合保存所有的合法序列,每遍历到一个字符,看它是否能添加在已有的序列后面,即遍历set中已存在的所有序列,别忘了每一个单独的字符也是一个合法序列。

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
#include<vector>
#include<queue>
#include<set> 
using namespace std;
set<string>s;
set<string>::iterator it;
string a,x,c;
int main()
{
	cin>>a;
	int i,n,m;
	m=a.length();
	for(i=0;i<m;i++)
	{
		for(it=s.begin();it!=s.end();it++)
		{
			x=*it;
			n=x.length();
			if(x[n-1]<a[i])
			{
				x.push_back(a[i]);
				s.insert(x);
			}
		}
		c.erase();
		c.push_back(a[i]);
		s.insert(c);
	}
	long long ans=s.size();
	cout<<ans<<endl;
	
	return 0;
}

字符串:

tocyjkdzcieoiodfpbgcncsrjbhmugdnojjddhllnofawllbhfiadgdcdjstemphmnjihecoapdjjrprrqnhgccevdarufmliqijgihhfgdcmxvicfauachlifhafpdccfseflcdgjncadfclvfmadvrnaaahahndsikzssoywakgnfjjaihtniptwoulxbaeqkqhfwl

答案:3616159

5.玩具蛇

思路:任意起点,任意终点,求不同的路线条数,4*4矩阵,深搜即可。

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
using namespace std;
int book[10][10];
int nextx[4]={-1,1,0,0};
int nexty[4]={0,0,-1,1};
long long ans;
void dfs(int x,int y,int cnt)
{
	if(cnt==16)
	{
		ans++;
		return;
	}
	int i;
	for(i=0;i<4;i++)
	{
		int nx=x+nextx[i];
		int ny=y+nexty[i];
		if(nx>=1&&nx<=4&&ny>=1&&ny<=4&&book[nx][ny]==0)
		{
			book[nx][ny]=1;
			dfs(nx,ny,cnt+1);
			book[nx][ny]=0;
		}
	}
}
int main()
{
	int i,j;
	for(i=1;i<=4;i++)
	{
		for(j=1;j<=4;j++)
		{
			book[i][j]=1;
			dfs(i,j,1);
			book[i][j]=0;
		}
	}
	cout<<ans<<endl;
	
	return 0;
}

答案:552

6.皮亚诺曲线距离

思路:

代码:

7.游园安排

思路:最长上升子序列的变形题,输出最长的序列,如果答案有多个,输出字典序最小的那个。

代码:

8.答疑

思路:贪心,关键看怎么排序,试了几个都不太对,最后发现是总用时少的排在前面就过了。

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
using namespace std;
struct node{
	long long a,b;
}; 
node m[1010];
bool cmp(node n1,node n2){
	return n1.a+n1.b<=n2.a+n2.b;
}
int main()
{
	int i,n;
	long long x,y,z,ans=0,sum=0;
	cin>>n;
	for(i=0;i<n;i++)
	{
		cin>>x>>y>>z;
		m[i].a=x+y;
		m[i].b=z;
	}
	sort(m,m+n,cmp);
	for(i=0;i<n;i++)
	{
		sum+=m[i].a;
		ans+=sum;
		sum+=m[i].b;
	}
	cout<<ans<<endl;
	
	return 0;
}

9.出租车

10.质数行者

思路:直接深搜,肯定会t

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
using namespace std;
int prime[1010],isprime[1010],num;
void init()
{
	int i,j;
	for(i=2;i<=1000;i++)
	{
		if(isprime[i]==0)
			prime[num++]=i;
		for(j=0;j<num&&i*prime[j]<=1000;j++)
		{
			isprime[i*prime[j]]=1;
			if(i%prime[j]==0)
				break;
		}
	}
}
int n,m,w,x1,y3,z1,x2,y2,z2;
long long ans;
long long mod=1000000007;
void dfs(int x,int y,int z)
{
	if(x==x1&&y==y3&&z==z1||x==x2&&y==y2&&z==z2)
		return;
	if(x==n&&y==m&&z==w)
	{
		ans++;
		ans%=mod;
		return;
	}
	for(int i=0;i<num;i++)
	{
		if(x+prime[i]<=n)
			dfs(x+prime[i],y,z);
		if(y+prime[i]<=m)
			dfs(x,y+prime[i],z);
		if(z+prime[i]<=w)
			dfs(x,y,z+prime[i]);
	}
}
int main()
{
	init();
	cin>>n>>m>>w;
	cin>>x1>>y3>>z1>>x2>>y2>>z2;
	dfs(1,1,1);
 	cout<<ans<<endl;
    return 0;
}

或者放弃大数据,记忆或搜索,只考虑300以内的数据,还能得60%的分

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
using namespace std;
int prime[1010],isprime[1010],num;
void init()
{
	int i,j;
	for(i=2;i<=1000;i++)
	{
		if(isprime[i]==0)
			prime[num++]=i;
		for(j=0;j<num&&i*prime[j]<=1000;j++)
		{
			isprime[i*prime[j]]=1;
			if(i%prime[j]==0)
				break;
		}
	}
}
int n,m,w,x1,y3,z1,x2,y2,z2;
long long ans;
long long mod=1000000007;
int judge(int x,int y,int z)
{
	if(x==x1&&y==y3&&z==z1||x==x2&&y==y2&&z==z2)
		return 0;
	else
		return 1;
}
int f[310][310][310];
int dfs(int x,int y,int z)
{
	if(x==n&&y==m&&z==w)
		return 1;
	if(f[x][y][z]!=-1) 
		return f[x][y][z];
	int c=0;
	for(int i=0;i<num;i++)
	{
		if(x+prime[i]<=n&&judge(x+prime[i],y,z))
			c=(c+dfs(x+prime[i],y,z))%mod;
		if(y+prime[i]<=m&&judge(x,y+prime[i],z))
			c=(c+dfs(x,y+prime[i],z))%mod;
		if(z+prime[i]<=w&&judge(x,y,z+prime[i]))
			c=(c+dfs(x,y,z+prime[i]))%mod;
	}
	return f[x][y][z]=c;
}
int main()
{
	init();
	cin>>n>>m>>w;
	cin>>x1>>y3>>z1>>x2>>y2>>z2;
	memset(f,-1,sizeof(f));
 	cout<<dfs(1,1,1)<<endl;
    return 0;
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值