洛谷刷题Day3——P1217+P3392+P1149

1. P1217 [USACO1.5] 回文质数 Prime Palindromes

题目描述

因为 151 151 151 既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以 151 151 151 是回文质数。
写一个程序来找出范围 [ a , b ] ( 5 ≤ a < b ≤ 100 , 000 , 000 ) [a,b] (5 \le a < b \le 100,000,000) [a,b](5a<b100,000,000)(一亿)间的所有回文质数。

输入格式

第一行输入两个正整数 a a a b b b

输出格式

输出一个回文质数的列表,一行一个。

输入输出样例 #1

输入 #1

5 500

输出 #1

5
7
11
101
131
151
181
191
313
353
373
383

代码

#include <iostream>
#include <vector>
using namespace std;
int a, b;
bool is_prime(int num)
{
    for (int i = 2; i <= num / i; i ++)
        if (num % i == 0) return false;
    return true;
}
bool is_recycle(int num)
{
    int sum = 0, cnum = num;
    while (num)
    {
        sum = sum * 10 + num % 10;
        num /= 10;
    }
    if (sum == cnum) return true;
    return false;
}
int main()
{
    cin >> a >> b;
    // 5-100000000(10^8)之间回文素数最大不超过10000000(10^7),然后就能进行一个简单的判断
    if (b > 1e7) b = 1e7;
    vector<int> recycle;
    for (int i = a; i <= b; i ++)
        if (is_recycle(i)) recycle.push_back(i);
    for (auto r : recycle)
        if (is_prime(r)) cout << r << endl;
    return 0;
}

2. P3392 涂条纹

题目描述

只要一个由 N × M N \times M N×M 个小方块组成的旗帜符合如下规则,就是合法的图案。

  • 从最上方若干行(至少一行)的格子全部是白色的;
  • 接下来若干行(至少一行)的格子全部是蓝色的;
  • 剩下的行(至少一行)全部是红色的;

现有一个棋盘状的布,分成了 N N N M M M 列的格子,每个格子是白色蓝色红色之一,小 a 希望把这个布改成合法图案,方法是在一些格子上涂颜料,盖住之前的颜色。
小 A 很懒,希望涂最少的格子,使这块布成为一个合法的图案。

输入格式

第一行是两个整数 N , M N,M N,M
接下来 N N N 行是一个矩阵,矩阵的每一个小方块是 W(白),B(蓝),R(红)中的一个。

输出格式

一个整数,表示至少需要涂多少块。

输入输出样例 #1

输入 #1

4 5
WRWRW
BWRWB
WRWRW
RWBWR

输出 #1

11

样例解释

目标状态是:

WWWWW
BBBBB
RRRRR
RRRRR

一共需要改 11 11 11 个格子。

数据范围

对于 100 % 100\% 100% 的数据, N , M ≤ 50 N,M \leq 50 N,M50

代码

#include <iostream>
using namespace std;
const int N = 55, INF = 0x3f3f3f3f;
int w[N], b[N], r[N];
char g[N][N];
int n, m;
int get_num(int i, char ch)
{
    int num = 0;
    for (int j = 1; j <= m; j ++)
        if (g[i][j] != ch)
            num ++;
    return num;
}
int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i ++)
        for (int j = 1; j <= m; j ++)
            cin >> g[i][j];
    // w[i]:前i行需要全涂成W的格子个数
    // b[i]:前i行需要全涂成B的格子个数
    // r[i]:前i行需要全涂成R的格子个数
    for (int i = 1; i <= n; i ++)
    {
        w[i] = w[i - 1] + get_num(i, 'W');
        b[i] = b[i - 1] + get_num(i, 'B');
        r[i] = r[i - 1] + get_num(i, 'R');
        // cout << w[i] << ' ' << b[i] << ' ' << r[i] << endl;
    }
    // 假如说[1, i]为W,[i + 1, j]为B,[j + 1, n]为R
    // 则,答案是w[i] + b[j] - b[i] + r[n] - r[j]最小
    int res = INF;
    for (int i = 1; i <= n - 2; i ++)
        for (int j = i + 1; j <= n - 1; j ++)
            res = min(res, w[i] + b[j] - b[i] + r[n] - r[j]);
    cout << res << endl;
    return 0;
}

3. P1149 [NOIP 2008 提高组] 火柴棒等式

题目描述

给你 n n n 根火柴棍,你可以拼出多少个形如 A + B = C A+B=C A+B=C 的等式?等式中的 A A A B B B C C C 是用火柴棍拼出的整数(若该数非零,则最高位不能是 0 0 0)。用火柴棍拼数字 0 ∼ 9 0\sim9 09 的拼法如图所示:

注意:

  1. 加号与等号各自需要两根火柴棍;
  2. 如果 A ≠ B A\neq B A=B,则 A + B = C A+B=C A+B=C B + A = C B+A=C B+A=C 视为不同的等式( A , B , C ≥ 0 A,B,C\geq0 A,B,C0);
  3. n n n 根火柴棍必须全部用上。

输入格式

一个整数 n ( 1 ≤ n ≤ 24 ) n(1 \leq n\leq 24) n(1n24)

输出格式

一个整数,能拼成的不同等式的数目。

输入输出样例 #1

输入 #1

14

输出 #1

2

输入输出样例 #2

输入 #2

18

输出 #2

9

说明/提示

【输入输出样例 1 解释】

2 2 2 个等式为 0 + 1 = 1 0+1=1 0+1=1 1 + 0 = 1 1+0=1 1+0=1

【输入输出样例 2 解释】

9 9 9 个等式为

0 + 4 = 4 0+4=4 0+4=4 0 + 11 = 11 0+11=11 0+11=11 1 + 10 = 11 1+10=11 1+10=11 2 + 2 = 4 2+2=4 2+2=4 2 + 7 = 9 2+7=9 2+7=9 4 + 0 = 4 4+0=4 4+0=4 7 + 2 = 9 7+2=9 7+2=9 10 + 1 = 11 10+1=11 10+1=11 11 + 0 = 11 11+0=11 11+0=11

代码

#include <iostream>
#include <vector>
using namespace std;
const int N = 15;
int sticks[10] = {
    6, 2, 5, 5, 4,
    5, 6, 3, 7, 6
};
int n, cnt;
int trans(int a)
{
    // 不加if,肯定bbq
    if (a == 0) return sticks[0];
    int sum = 0;
    while (a)
    {
        sum += sticks[a % 10];
        a /= 10;
    }
    return sum;
}
int main()
{
    cin >> n;
    n -= 4;
    // 枚举数字a + b = c
    // 为什么枚举a,b是1000呢
    // 因为题目中n=24,771+0=771满足题意
    for (int i = 0; i <= 1000; i ++)
        for (int j = 0; j <= 1000; j ++)
            {
                // 找到数字对应的火柴数num1 num2 num3
                int num1 = trans(i), num2 = trans(j),num3 = trans(i + j);
                if (num1 + num2 + num3 == n) 
                {
                    // cout << i << ' ' << j << ' ' << i + j << endl;
                    //cout << num1 << ' ' << num2 << ' ' << num3 << endl;
                    cnt ++;
                }
            }
    cout << cnt << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值