2019蓝桥杯B组决赛题解

A

题解:暴力枚举判断下第三个数是否能分解为k*k即可。
 


B

题解:素数筛筛2-2019中素数,再用01背包。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>

using namespace std;

typedef long long LL;

const int N = 3000;
int primes[N], cnt;
bool st[N];

LL dp[500][2050];
int main()
{
    for(int i = 2; i <= 2019; i++) {
        if(!st[i]) primes[cnt++] = i;
        for(int j = 0; j < cnt && i * primes[j] <= 2019; j++) {
            st[i * primes[j]] = true;
            if(i % primes[j] == 0) break;
        }
    }
  
    for(int i = cnt; i >= 1; i--) primes[i] = primes[i-1];
    
    dp[0][0] = 1;
    for(int i = 1; i <= cnt; i++)  // 前i个素数中总和为j的方案数
    {
        for(int j = 0; j <= 2019; j++)
        {
            dp[i][j] = dp[i-1][j];
            if(j >= primes[i]) dp[i][j] += dp[i-1][j - primes[i]];
        }
    }
    

    cout << dp[cnt][2019] << endl;
    return 0;    
}

 


C

题解:通过观察,要使分开后的两部分能拼接,分开的两部分必须以左下右上连成斜线对称。这样,只需对一边进行dfs即可。

#include <iostream>
#include <string>

using namespace std;

const int N = 7;

int ans;
bool st[10][10];
int dx[] = {0, 1, 0, -1};
int dy[] = {1, 0, -1, 0};

void dfs(int x, int y, string s)
{
    if(x + y == N) {
        ans++;
        //cout << s << endl;
        return;
    }
    
    for(int i = 0; i < 4; i++)
    {
        int nx = x + dx[i], ny = y + dy[i];
        
        if(nx > N || nx < 0 || ny > N || ny < 0 || st[nx][ny]) continue;

        if((nx == 0 && x != 0) && (x != 1 || y != 0)) continue;
        if(ny == 0 && y != 0) continue;
        

        st[nx][ny] = true;
        string temp =s +  (char)(nx + '0') + ',' + (char)(ny + '0') + ' ';
        dfs(nx, ny, temp);
        st[nx][ny] = false;
    }
}

int main()
{
    st[N][0] = true;
    st[N-1][0] = true;
    string str = "";
    dfs(N - 1, 0, str);
    
    cout << ans + 1; 
    
    return 0;
}

 


D

题解:从小到大遍历每个数,对其分解质因数,记录每个因数出现的次数为a1, a2, a3…, 则该数的约数个数为(a1 + 1) * (a2 + 1) * (a3 + 1) …(加一是因为该因数可以不选)

#include <iostream>
#include <set>

using namespace std;

typedef long long LL;


int cal(int x)
{
    int num = 0;
    int ans[110] = {0};
    for(int i = 2; i <= x/i; i++)
    {
        if(x % i == 0)
        {
            while(x % i == 0)
            {
                x /= i;
                ans[num]++;
            }
            num++;
        }
    }
    if(x != 1) ans[num++] = 1;
    
    int res = 1;
    for(int i = 0; i < num; i++) res *= ans[i] + 1;
    
    return res;
}

int main()
{

    for(int i = 100; ; i++)
    {
        if(cal(i) == 100)
        {
            cout << i;
            break;
        }
    }
    
    return 0;
    
}

E

题解: 从与起点相接的2个点分别开始dfs,则搜索的结束点即为另一个点,同时将路径长度减去2,因为路径开始和结束都未到起点,所以少了2
 

#include <iostream>
#include <string>
#include <set>
using namespace std;

int dx[] = {0, 1, 0, -1};
int dy[] = {-1, 0, 1, 0};
int st[10][10];
int ans;


void dfs(int x, int y, int len, int endx, int endy, string path)
{
  if(len > 10) return;
  if(x == endx && y == endy)
  {
    ans++;
   //  cout << path << " " << len << endl;

    return;
  }

  for(int i = 0; i < 4; i++)
  {
    int nx = x + dx[i];
    int ny = y + dy[i];

    if(nx >= 0 && nx <= 5 && ny >= 0 && ny <= 5 && !st[nx][ny]) 
    {
      st[nx][ny] = true;
      string np = path + char(nx + '0') + ',' + char(ny + '0') + ' ';
      dfs(nx, ny, len+1, endx, endy, np);
      st[nx][ny] = false;
    }
  }
}
int main()
{
  string str = "";
  st[0][0] = true;
  
  st[1][0] = true;
  dfs(1, 0, 0, 0, 1, str);
  st[1][0] = false;
    
  st[0][1] = true;
  dfs(0, 1, 0, 1, 0, str);
  st[0][1] = false;
  
  cout << ans<< endl;
  

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值