算法-蓝桥杯原题

目录

2019年第十届蓝桥杯国赛B组试题A-平方序列

2019年第十届蓝桥杯国赛B组试题B-质数拆分

2019年第十届蓝桥杯国赛B组试题D-求值

2019年第十届蓝桥杯国赛B组试题E-路径计数

2019年第十届蓝桥杯国赛B组试题F-最优包含

2019年第十届蓝桥杯国赛B组试题G-排列数

2018年第九届蓝桥杯国赛B组试题A-换零钞

2018年第九届蓝桥杯国赛B组试题B-激光样式

2018年第九届蓝桥杯国赛B组试题D-调手表

2017年第八届蓝桥杯国赛B组试题A-36进制

2017年第八届蓝桥杯国赛B组试题B-瓷砖样式

2017年第八届蓝桥杯国赛B组试题E-对局匹配

2016年第七届蓝桥杯国赛B组试题A-一步之遥

2016年第七届蓝桥杯国赛B组试题B-凑平方数

 练习题:星期一


2019年第十届蓝桥杯国赛B组试题A-平方序列

【问题描述】
小明想找到两个正整数 X 和 Y,满足

  • 2019 < X < Y;

  • 20192 , X2 , Y2 组成等差数列。

请你求出在所有可能的解中,X + Y 的最小值是多少?

答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。
本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。


答案:7020


题解 暴力即可,可用等差数列知识适当优化a + c = 2b,∴ c = 2b - a (不过填空题可以但没必要)

#include<bits/stdc++.h>
using namespace std;

int main(){

    long long x=2019, y,z;
    for(int y=2020; ;y++){
        z=sqrt(2*y*y-x*x);
        if(z*z==2*y*y - x*x){
            cout<<y+z;
            break;
        }
            
    }
    return 0;

}

2019年第十届蓝桥杯国赛B组试题B-质数拆分

【问题描述】

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


答案:55965365465060


题解
01背包:

#include <bits/stdc++.h>
using namespace std;

const int N = 2020;

int dp[N];
int st[N], prim[N];
int k;
//筛一遍素数
void init()
{
    st[0] = st[1] = 0;
    st[2] = 1;
    for (int i = 2; i <= 2019; i++)
    {
        if (!st[i])
        {
            prim[k++] = i;
            for (int j = i + i; j <= 2019; j += i)
            {
                st[i] = true;
            }
        }
    }
}

int main()
{
    init();

    dp[0] = 1;
    for (int i = 1; i < k; i++)
    {
        for (int j = 2019; j >= prim[i]; j--)
        {
            dp[j] += dp[j-prim[i]];
        }
    }
    cout << dp[2019];
    return 0;
}

2019年第十届蓝桥杯国赛B组试题D-求值

【问题描述】
学习了约数后,小明对于约数很好奇,他发现,给定一个正整数 t,总是可以找到含有 t 个约数的整数。

小明对于含有 t 个约数的最小数非常感兴趣,并把它定义为 St 。

例如 S1 = 1, S2 = 2, S3 = 4, S4 = 6,···。

现在小明想知道,当 t = 100 时,St 是多少?即 S100 是多少?

答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。
本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。


答案:45360


题解
暴力

#include<bits/stdc++.h>
using namespace std;


int judge(int n){
    int cnt=0;
    for(int i=1; i<=n; i++){
        if(n%i==0)
            cnt++;
    }
    return cnt;
}

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

2019年第十届蓝桥杯国赛B组试题E-路径计数

【问题描述】
从一个 5 x 5 的方格矩阵的左上角出发,沿着方格的边走,满足以下条件的路线有多少种?

  • 总长度不超过 12;
  • 最后回到左上角;
  • 路线不自交;
  • 不走出 5 x 5 的方格矩阵范围之外。

如下图所示,ABC 是三种合法的路线。注意 B 和 C 由于方向不同,所以视为不同的路线。

在这里插入图片描述
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。
本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。


答案:202


题解
DFS:

#include <bits/stdc++.h>
using namespace std;

int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; //上右下左
int vis[10][10];
int cnt;

void dfs(int x, int y, int step)
{
    if (step > 12)
        return;
    if (x == 0 && y == 0 && step > 2)
    {
        cnt++;
        return;
    }
    for (int i = 0; i < 4; i++)
    {
        int a = x + dx[i], b = y + dy[i];
        if (a >=0  && a < 6 && b >=0  && b < 6 && !vis[a][b])
        {
            vis[a][b] = 1;
            dfs(a, b, step + 1);
            vis[a][b] = 0;
        }
    }
}

int main()
{
    dfs(0, 0, 0);
    cout << cnt;
    return 0;
}

2019年第十届蓝桥杯国赛B组试题F-最优包含

我们称一个字符串 SS 包含字符串 TT 是指 TT 是 SS 的一个子序列,即可以从字符串 SS 中抽出若干个字符,它们按原来的顺序组合成一个新的字符串与 TT 完全一样。

给定两个字符串 SS 和 TT,请问最少修改 SS 中的多少个字符,能使 SS 包含 TT?

输入格式

输入两行,每行一个字符串。

第一行的字符串为 SS,第二行的字符串为 TT。

两个字符串均非空而且只包含大写英文字母。

输出格式

输出一个整数,表示答案。

数据范围

1≤|T|≤|S|≤10001≤|T|≤|S|≤1000

输入样例:

ABCDEABCD
XAABZ

输出样例:

3

题解
#include<bits/stdc++.h>
using namespace std;

// 解题思路:动态规划。
// dp[i][j]表示令T的前j个字符成为S的前i个字符的子序列需要修改的字符个数。
// 先初始化i=j和j=0的情况。
// 状态转移方程:
// if(s[i]==t[j])
//   dp[i][j]=dp[i-1][j-1];
// else
//   dp[i][j]=min(dp[i-1][j],dp[i-1][j-1]+1);

const int N = 1e3+10;
int dp[N][N];
string s,t;

int main(){
cin>>s>>t;

int ls= s.size();
int lt= t.size();

if(s[0]!=t[0]){
    dp[0][0]=1;
}

//ABCDABCD  S
//AABCX    T
for (int i = 1; i < lt; i++)
    if (s[i] == t[i])
        dp[i][i] = dp[i - 1][i - 1];
    else
        dp[i][i] = dp[i - 1][i - 1] + 1;


for (int i = 1; i < ls; i++)
{
    if (s[i] == t[0])
        dp[i][0] = 0;
    else
        dp[i][0] = dp[i - 1][0];
}

for (int j = 1; j < lt; j++)
{
    for (int i = j + 1; i < ls; i++)
    {
        if (s[i] == t[j])
            dp[i][j] = dp[i - 1][j - 1];   //21=10  31=20   41=30        32=21   42=31
        else
            dp[i][j] = min(dp[i - 1][j], dp[i - 1][j - 1] + 1); //变j还是不变j   21=11/10  31=21/20    32=22/21 初始化考虑

    }
}
printf("%d\n", dp[ls - 1][lt - 1]);

return 0;

}

2019年第十届蓝桥杯国赛B组试题G-排列数

在一个排列中,一个折点是指排列中的一个元素,它同时小于两边的元素,或者同时大于两边的元素。

对于一个 1∼n1∼n 的排列,如果可以将这个排列中包含 tt 个折点,则它称为一个 t+1t+1 单调序列。

例如,排列 (1,4,2,3)(1,4,2,3) 是一个 33 单调序列,其中 44 和 22 都是折点。

给定 nn 和 kk,请问 1∼n1∼n 的所有排列中有多少个 kk 单调队列?

输入格式

输入一行包含两个整数 n,kn,k。

输出格式

输出一个整数,表示答案。

答案可能很大,你可需要输出满足条件的排列数量除以 123456123456 的余数即可。

数据范围

1≤k≤n≤5001≤k≤n≤500

输入样例:

4 2

输出样例:

12

题解
#include <bits/stdc++.h>
using namespace std;

int n, k;
int a[501];

void init(int n)
{
for (int i = 1; i <= n; i++)
{
a[i] = i;
}
}

int main()
{
cin >> n >> k;
int sum = 0;
init(n);

do
{
    int cnt = 0;
    for (int i = 2; i <= n-1; i++)
    {
        if ((a[i] > a[i + 1] && a[i] > a[i - 1]) || (a[i] < a[i + 1] && a[i] < a[i - 1]))
        {
            cnt++;
        }
    }

    if (cnt+1 == k)
    {
        sum++;
    }

} while (next_permutation(a + 1, a + 1 + n));
cout << sum;
return 0;

}

2018年第九届蓝桥杯国赛B组试题A-换零钞

【问题描述】

x星球的钞票的面额只有:100元,5元,2元,1元,共4种。
小明去x星旅游,他手里只有2张100元的x星币,太不方便,恰好路过x星银行就去换零钱。
小明有点强迫症,他坚持要求200元换出的零钞中2元的张数刚好是1元的张数的10倍,剩下的当然都是5元面额的。
银行的工作人员有点为难,你能帮助算出:在满足小明要求的前提下,最少要换给他多少张钞票吗?
(5元,2元,1元面额的必须都有,不能是0)

【答案提交】
注意,需要提交的是一个整数,不要填写任何多余的内容。


答案:74


题解
暴力:

#include <bits/stdc++.h>
using namespace std;

int main()
{
   for(int i=40; i>0; i--)
       for (int j = 200; j >0; j--)
       {
           if((i*5+j*1+j*10*2)==200){
               cout<<i+j+j*10<<endl;
               break;
           }
       }
   
   return 0;
}

2018年第九届蓝桥杯国赛B组试题B-激光样式

【问题描述】

x星球的盛大节日为增加气氛,用30台机光器一字排开,向太空中打出光柱。
安装调试的时候才发现,不知什么原因,相邻的两台激光器不能同时打开!
国王很想知道,在目前这种bug存在的情况下,一共能打出多少种激光效果?
显然,如果只有3台机器,一共可以成5种样式,即:
1、全都关上(sorry, 此时无声胜有声,这也算一种)
2、开一台,共3种
3、开两台,只1种
但是30台就不好算了,国王只好请你帮忙了。

【答案提交】
要求提交一个整数,表示30台激光器能形成的样式种数。
注意,只提交一个整数,不要填写任何多余的内容。


答案:2178309


题解
DFS:

#include <bits/stdc++.h>
using namespace std;

int ans;
const int N = 30;
bool st[N];

void dfs(int u)
{
    if(u == 30)
    {
        ans ++;
        return;
    }
                          // 每一次都有两种选择  

    dfs(u + 1);              // 1、关闭

    if(!st[u - 1])           // 2、打开
    {
        st[u] = true;
        dfs(u + 1);
        st[u] = false;
    }
}

int main()
{
    dfs(0);
    cout << ans << endl;
    return 0;
}

2018年第九届蓝桥杯国赛B组试题D-调手表

问题描述
小明买了块高端大气上档次的电子手表,他正准备调时间呢。

在 M78 星云,时间的计量单位和地球上不同,M78 星云的一个小时有 n 分钟。

大家都知道,手表只有一个按钮可以把当前的数加一。

在调分钟的时候,如果当前显示的数是 0 ,那么按一下按钮就会变成 1,再按一次变成 2;如果是 n - 1,那么按一次后会变成 0 。

作为强迫症患者,小明一定要把手表的时间调对。如果手表上的时间比当前时间多 1,则要按 n - 1 次加一按钮才能调回正确时间。

小明想,如果手表可以再添加一个按钮,表示把当前的数加 k 该多好啊……

他想知道,如果有了这个 +k 按钮,按照最优策略按键,从任意一个分钟数调到另外任意一个分钟数最多要按多少次。

注意,按 +k 按钮时,如果加 k 后数字超过 n - 1,则会对 n 取模。

比如,n = 10, k = 6 的时候,假设当前时间是 0,连按 2 次 +k 按钮,则调为 2。

输入格式
一行两个整数 n, k,意义如题。

输出格式
一行一个整数,表示按照最优策略按键,从一个时间调到另一个时间最多要按多少次。

样例输入
5 3

样例输出
2

样例解释
如果时间正确则按 0 次。否则要按的次数和操作系列之间的关系如下:
1:+1
2:+1, +1
3:+3
4:+3, +1

数据范围
对于 30% 的数据 0 < k < n ≤ 5
对于 60% 的数据 0 < k < n ≤ 100
对于 100% 的数据 0 < k < n ≤ 105


题解
BFS:

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1005, inf = 1 << 29, mod = 1000000007;

int d[maxn];

void bfs()
{
    queue<int> q;
    q.push(0);
    d[0] = 0;

    while (!q.empty())
    {
        int t = q.front();
        q.pop();

        int a = (t + 1) % n;
        if (d[a] == -1)
        {
            d[a] = d[t] + 1;
            q.push(a);
        }
        int b = (t + k) % n;
        if (d[b] == -1)
        {
            d[b] = d[t] + 1;
            q.push(b);
        }
    }
}

int main()
{
    memset(d, -1, sizeof(d));
    cin >> n >> k;
    bfs();
    int ans = 0;
    for (int i = 0; i < n; i++)
        ans = max(ans, d[i]);
    cout << ans;

    return 0;
}

2017年第八届蓝桥杯国赛B组试题A-36进制

【问题描述】

对于16进制,我们使用字母A-F来表示10及以上的数字。
如法炮制,一直用到字母Z,就可以表示36进制。
36进制中,A表示10,Z表示35,AA表示370
你能算出 MANY 表示的数字用10进制表示是多少吗?

【答案提交】
请提交一个整数,不要填写任何多余的内容(比如,说明文字)


答案:1040254


题解一
手算:

22 * 363 + 10 * 362 + 23 * 361 + 34 * 360

题解二
模拟:

#include<bits/stdc++.h>
using  namespace std;


int main(){
    string s="MANY";
    int sum=0;
    for(int i=0; i<s.size(); i++){
        sum=sum*36+s[i]-'A'+10;
    }
    cout<<sum;
    return 0;
    
}

2017年第八届蓝桥杯国赛B组试题B-瓷砖样式

问题描述
小明家的一面装饰墙原来是 3 × 10 的小方格。现在手头有一批刚好能盖住 2 个小方格的长方形瓷砖。

瓷砖只有两种颜色:黄色和橙色。小明想知道,对于这么简陋的原料,可以贴出多少种不同的花样来。

小明有个小小的强迫症:忍受不了任何 2 × 2 的小格子是同一种颜色。

瓷砖不能切割,不能重叠,也不能只铺一部分。另外,只考虑组合图案,请忽略瓷砖的拼缝

显然,对于 2 × 3 个小格子来说,口算都可以知道:一共 10 种贴法,如图所示:

在这里插入图片描述

但对于 3 ×10 的格子呢?肯定是个不小的数目,请你利用计算机的威力算出该数字。

答案提交
注意:你需要提交的是一个整数,不要填写任何多余的内容(比如:说明性文字)


答案:101466


题解
DFS & set:

解题思路
一层一层地铺放瓷砖,铺放完毕后,记录所有合法样式,并用 set 去重。

  • -1

    该位置未放置瓷砖

  • 0

    放置的是黄色瓷砖

  • 1

    放置的是橙色瓷砖

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1005, inf = 1 << 29, mod = 1000000007;
const double pi = acos(-1.0);
typedef long long ll;
;
inline int gcd(int x, int y)
{
    if (!x)
        return y;
    return gcd(y % x, x);
}
int n, m, k, max_sum, min_sum;
int a[maxn], b[maxn];
int aa[maxn][maxn], bb[maxn][maxn], dp[maxn][maxn];
int dir[][2] = {{0, 1}, {-1, 0}, {0, -1}, {1, 0}, {-1, 1}, {-1, -1}, {1, -1}, {1, 1}};
vector<int> vi;

set<string> st;

bool judge()
{
    for (int i = 1; i < 3; i++)
    {
        for (int j = 1; j < 10; j++)
        {
            if ((aa[i][j] + aa[i + 1][j] + aa[i][j + 1] + aa[i + 1][j + 1]) % 4 == 0)
            {
                return false;
            }
        }
    }
    return true;
}

void dfs(int x, int y)
{
    if (x == 4)
    {
        if (judge())
        {
            string ans = "";
            for (int i = 1; i <= 3; i++)
            {
                for (int j = 1; j <= 10; j++)
                {
                    char *temp;
                    itoa(aa[i][j], temp, 10);
                    ans += temp;
                }
            }
            st.insert(ans);
        }
        return;
    }

    if (aa[x][y] == -1)
    {
        //横着放
        if (y + 1 <= 10 && aa[x][y + 1] == -1)
        {
            //两种颜色
            for (int i = 0; i < 2; ++i)
            {
                aa[x][y] = aa[x][y + 1] = i;
                if (y + 2 <= 10)
                    dfs(x, y + 1);
                else
                    dfs(x + 1, 1);
                aa[x][y] = aa[x][y + 1] = -1;
            }
        }

        //竖着放
        if (x + 1 <= 3 && aa[x + 1][y] == -1)
        {
            for (int i = 0; i < 2; i++)
            {
                aa[x][y] = aa[x + 1][y] = i;
                if (y + 1 <= 10)
                    dfs(x, y + 1);
                else
                    dfs(x + 1, 1);
                aa[x][y] = aa[x + 1][y] = -1;
            }
        }
    }
    else
    {
        if (y == 10)
            dfs(x + 1, 1);
        else
            dfs(x, y + 1);
    }
}

int main()
{
    memset(aa, -1, sizeof(aa));
    dfs(1, 1);
    cout << st.size() << endl;
    return 0;
}

2017年第八届蓝桥杯国赛B组试题E-对局匹配

问题描述
小明喜欢在一个围棋网站上找别人在线对弈。这个网站上所有注册用户都有一个积分,代表他的围棋水平。

小明发现网站的自动对局系统在匹配对手时,只会将积分差恰好是 K 的两名用户匹配在一起。

如果两人分差小于或大于 K,系统都不会将他们匹配。

现在小明知道这个网站总共有 N 名用户,以及他们的积分分别是 A1, A2, … AN。

小明想了解最多可能有多少名用户同时在线寻找对手,但是系统却一场对局都匹配不起来 (任意两名用户积分差不等于 K)?

输入格式
第一行包含两个个整数 N 和 K。
第二行包含N个整数 A1, A2, … AN。

输出格式
一个整数,代表答案。

样例输入1
10 0
1 4 2 8 5 7 1 4 2 8

样例输出1
6

样例输入2
10 1
2 1 1 1 1 4 4 3 4 4

样例输出2
8

数据范围
对于 30% 的数据,1 ≤ N ≤ 10
对于 100% 的数据,1 ≤ N ≤ 105, 0 ≤ Ai ≤ 105, 0 ≤ K ≤ 105


题解一
DFS(会超时)

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1005, inf = 1 << 29, mod = 1000000007;
const double pi = acos(-1.0);
typedef long long ll;
;
inline int gcd(int x, int y)
{
    if (!x)
        return y;
    return gcd(y % x, x);
}
int n, m, k, max_sum, min_sum;
int a[maxn], b[maxn], s[maxn], st[maxn];
int aa[maxn][maxn], bb[maxn][maxn], dp[maxn][maxn];
int dir[][2] = {{0, 1}, {-1, 0}, {0, -1}, {1, 0}, {-1, 1}, {-1, -1}, {1, -1}, {1, 1}};
vector<int> vi;

bool judge(int u, int i)
{
    for (int j = 1; j < u; j++)
    {
        if (a[j] - s[i] == k || s[i] - a[j] == k)
            return false;
    }
    return true;
}

void dfs(int u)
{
    m = max(m, u - 1);
    for (int i = 1; i <= n; i++)
    {
        if (st[i] || !judge(u, i))
            continue;

        st[i] = true;
        a[u] = s[i];
        dfs(u + 1);
        st[i] = false;
    }
    return ;
}

int main()
{
    cin >> n >> k;
    for (int i = 1; i <= n; i++)
    {
        cin >> s[i];
    }
    dfs(1);
    cout<<m;
    return 0;
}

题解二
动态规划:

以第二个数据 2 1 1 1 1 4 4 3 4 4 为例,由于 k = 1,所以分成 1 组公差为 1 等差数列。

  • 等差数列:0 1 2 3 4 …
  • 出现次数:0 4 1 1 4 …

决策:由于相邻两项公差为 k,所以不能选择相邻的两项。

状态转移方程:

  • 当 i == 0f[i] = s[i]
  • 当 i == 1f[i] = max(f[i - 1], s[i])
  • 当 i >= 2f[i] = max(f[i - 1], f[i - 2] + s[i])
#include <iostream>
using namespace std;

const int N = 100010;

int n, k, x, ans;
int cnt[N], s[N], f[N];

int main()
{
	cin >> n >> k;

	for (int i = 1; i <= n; i ++)
	{
		cin >> x;
		cnt[x] ++;												// 统计每个积分出现的次数 
	}

	if(k == 0)													// k = 0 需要特判 
	{
		for (int i = 0; i < N; i ++)
			if(cnt[i]) ans ++;	
	}
	else
	{
		for (int i = 0; i < k; i ++)							// 分成 k 个公差为 k 的等差数列 
		{
			int u = 0;
			for (int j = i; j <= N; j += k)						// 首项分别为 i 出现的次数 
				s[u ++] = cnt[j];

			f[0] = s[0];
			for (int j = 1; j < u; j ++)
			{
				if(j == 1) f[j] = max(f[j - 1], s[j]);	
				else f[j] = max(f[j - 1], f[j - 2] + s[j]);
			}

			ans += f[u - 1];									// 加上每组等差数列选择的最大值
		}
	}

	cout << ans << endl;
	return 0;
}

2016年第七届蓝桥杯国赛B组试题A-一步之遥

问题描述】

从昏迷中醒来,小明发现自己被关在X星球的废矿车里。
矿车停在平直的废弃的轨道上。
他的面前是两个按钮,分别写着“F”和“B”。
小明突然记起来,这两个按钮可以控制矿车在轨道上前进和后退。
按F,会前进97米。按B会后退127米。
透过昏暗的灯光,小明看到自己前方1米远正好有个监控探头。
他必须设法使得矿车正好停在摄像头的下方,才有机会争取同伴的援助。
或许,通过多次操作F和B可以办到。
矿车上的动力已经不太足,黄色的警示灯在默默闪烁…
每次进行 F 或 B 操作都会消耗一定的能量。
小明飞快地计算,至少要多少次操作,才能把矿车准确地停在前方1米远的地方。
请填写为了达成目标,最少需要操作的次数。

【答案提交】
注意,需要提交的是一个整数,不要填写任何无关内容(比如:解释说明等)


答案:97


题解
枚举:

#include <iostream>
using namespace std;

int main()
{
    for (int i = 1; i < 100; i ++)
        for (int j = 1; j < 100; j ++)
            if(i * 97 - j * 127 == 1) cout << i + j << endl;

    return 0;        
}

2016年第七届蓝桥杯国赛B组试题B-凑平方数

问题描述
把 0 ~ 9 这 10 个数字,分成多个组,每个组恰好是一个平方数,这是能够办到的。

比如:0,36,5948721

再比如:{1098524736};{1,25,6390784};{0,4,289,15376} 等等…

注意,0 可以作为独立的数字,但不能作为多位数字的开始。

分组时,必须用完所有的数字,不能重复,不能遗漏。

如果不计较小组内数据的先后顺序,请问有多少种不同的分组方案?

答案提交
注意:需要提交的是一个整数,不要填写多余内容。


答案:300


题解
DFS:

#include<bits/stdc++.h>

using namespace std;

typedef long long LL;

LL used[10], tmp[10], s[10], k;
set<string> cnt;

void dfs(int u)
{
    if (u == 10)
    {
        copy(used, used + k, tmp); // 将 used 数组中的内容,复制给 tmp 数组
        sort(tmp, tmp + k);
        string ans = "";
        for (int i = 0; i < k; i++)
        {
            char s[20];
            sprintf(s, "%lld", tmp[i]); // 将数字转换成字符串
            ans += s;
            ans += '-'; // 每个平方数都以 '-' 隔开
        }
        cnt.insert(ans); // 存储答案,并去重
        return;
    }

    if (s[u] == 0) // 0 不能作为数字的开头,自成一组
    {
        used[k++] = 0;
        dfs(u + 1);
        used[--k] = 0;
    }
    else
    {
        LL t = 0;
        for (int i = u; i < 10; i++)
        {
            t = t * 10 + s[i];
            LL x = sqrt(t);
            if (x * x == t)
            {
                used[k++] = t;
                dfs(i + 1);
                used[--k] = 0;
            }
        }
    }
}

int main()
{
    for (int i = 0; i < 10; i++)
        s[i] = i;

    do
    {
        dfs(0);
        k = 0;
    } while (next_permutation(s, s + 10));

    cout << cnt.size() << endl;
    return 0;
}

 练习题:星期一

整个20世纪(1901年1月1日至2000年12月31日之间),一共有多少个星期一?(不要告诉我你不知道今天是星期几)

以下程序实现了这一功能,请你补全以下空白处内容:

提示:

判断1901年1月1日到2000年12月31的每一天是星期几,如果是星期一则统计的个数+1。
#include <stdio.h>
int main()
{
    int year, day, dayrun = 0, dayping = 0, sumday = 0;
    int count = 0;

    for (year = 1901; year <= 2000; year++)
    {
        if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
        {
            dayrun += 366;
        }
        else
        {
            dayping += 365;
        }
    }

    sumday = dayrun + dayping;

    __________________________;
    printf("%d", count);
    return 0;
}

Afor (day = 2; day <= sumday - 7; day++)
{
    count++;
}
Bfor (day = 2; day <= sumday - 7; day += 7)
{
    count++;
}
Cfor (day = 2; day < sumday; day += 7)
{
    count++;
}
Dfor (day = 2; day <= sumday; day += 7)
{
    count++;
}

答案:

for (day = 2; day <= sumday - 7; day += 7)
{
    count++;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

兔子递归

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值