2019蓝桥杯国赛C++B组

A:

1、2019<X<Y
2、2019^2, X^2, Y^2构成等差数列
满足条件的X和Y可能有多种情况,请给出X+Y的值,并且令X+Y尽可能的小。

思路:暴力求解

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
using namespace std;
int main()
{
	int i,j;
	for(i=2020;i<100000;i++)
	{
		for(j=i+1;j<100000;j++)
		{
			if(j*j-i*i==i*i-2019*2019)
			{
				cout<<i+j<<endl;
				return 0;
			}
		}
	} 
	
    return 0;
}

答案:7020

B:

2019可以被分解成若干个两两不同的素数,请问不同的分解方案有多少种?
注意:分解方案不考虑顺序,如2+2017=2019和2017+2=2019属于同一种方案。

思路:典型的01背包问题。

线性素数筛求出2019以内的所有素数,每个素数只能取或不取,不能多次出现,dp[j]表示前i个素数能组成数字j的方案数。

状态转移方程dp[j]+=dp[j-prime[i]];表示能构成数字j的方案数是以下两者之和:

(1)不取第i个素数,前i-1个素数能构成j的方案数。

(2)取第i个素数,能构成j的方案数,也就是构成数字(j-prime[i])的方案数。

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<map>
#include<vector>
using namespace std;
int prime[1010],isprime[2050],num;
long long dp[2050];
void init()
{
    int i,j;
    for(i=2;i<=2019;i++)
    {
        if(isprime[i]==1)
            prime[num++]=i;
        for(j=0;j<num&&i*prime[j]<=2019;j++)
        {
            isprime[i*prime[j]]=0;
            if(i%prime[j]==0)
                break;
        }
    }
}
int main()
{
    int i,j;
    for(i=0;i<=2019;i++)
        isprime[i]=1;
    dp[0]=1;
    init();
    for(i=0;i<num;i++)
        for(j=2019;j>=prime[i];j--)
            dp[j]+=dp[j-prime[i]];
    cout<<dp[2019]<<endl;

    return 0;
}

答案:55965365465060

C:

思路:搜索。切成两半,每部分都关于副对角线对称。切的时候只考虑左边的一半就可以,剩下的另一半一定也成立。

代码:

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

答案:2444

D:

有1个约数的最小数为1(1),有两个约数的最小数为2(1,2)……
有n个约数的最小数为Sn
S1=1 (1)
S2=2 (1 2)
S3=4 (1 2 4)
S4=6 (1 2 3 6)
求S100

思路:暴力

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<map>
#include<vector>
using namespace std;
int main()
{
    int i,j,cnt;
    for(i=100;;i++)
    {
        cnt=0;
        for(j=1;j<=i;j++)
        {
            if(i%j==0)
                cnt++;
        }
        if(cnt==100)
            break;
    }
    cout<<i;
    return 0;
}

答案:45360

E:

有一个5X5的方格。方格左上角顶点坐标为(0,0),右下角坐标为(5,5)。
求满足下列条件的路径条数:
1、起点和终点都是(0,0)
2、路径不自交
3、路径长度不大于12
4、对于每一个顶点,有上下左右四个方向可以走,但是不能越界。

思路:深搜

代码:

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

答案:206(需要剪掉两个路线(0,0)->(1,0)->(0,0)和(0,0)->(0,1)->(0,0),这两个路线都发生了路径自交)

F:

题目给定两个字符串S和T,保证S的长度不小于T的长度,问至少修改S的多少个字符,可以令T成为S的子序列。

样例输入1:

ABCDABCD
AABCX

样例输出1:

1

样例输入2:

ABCDABCD
XAAD

样例输出2:

2

样例输入3:

XBBBBBAC
ACC

样例输出3:

2

思路:dp

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<map>
#include<vector>
#define inf 0x3f3f3f3f
using namespace std;
int dp[1010][1010];
int main()
{
    char s[1010],t[1010];
    scanf("%s",s+1);
    getchar();
    scanf("%s",t+1);
    int n=strlen(s+1),m=strlen(t+1),i,j;
    memset(dp,inf,sizeof(dp));
    for(i=0;i<=n;i++)
        dp[i][0]=0;
    for(j=1;j<=m;j++)
    {
        for(i=j;i<=n;i++)
        {
            if(s[i]==t[j])
                dp[i][j]=dp[i-1][j-1];
            else
                dp[i][j]=min(dp[i-1][j-1]+1,dp[i-1][j]);
        }
    }
    cout<<dp[n][m]<<endl;
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值