2017 国庆清北刷题冲刺班《角谷猜想》

原创建时间:2018-07-04 20:05:44

不错的字符串模拟

题目描述

某个名字末尾是654321的小A同学是个大家眼中公认的学霸(虽然他永远不承认),他对题目的直觉到了一种可怕的地步,一眼看出题目的算法对他而言只是小 Case,他甚至能在看到一个证明的瞬间敏锐地判断出这个证明的真伪。

现在小A同学机缘巧合地看到了角古猜想(即对于\(x\)当它为奇数则\(x=3x+1\),\(x\)为偶数,则\(x=\frac{x}{2}\),一直重复这个步骤,则最终\(x\)会变为\(1\)),在看完这个猜想的一瞬间,他的直觉就来了——他认为角古猜想一定是错的!然后——他立刻就能找出反例!

他立刻在纸上写满了\(n\)(\(1<=n<=1000\))个小于\(10^L\)(\(0<=L<=10^4\))的正整数,打算放到他的grand super computer 上去跑,可是他突然觉得有些正整数不是很吉利,可能会干扰到他的最终结果,所以他打算把一些正整数加工一下。

小A觉得4、7、13都是不吉利的数字,所以要把所有正整数里的4、7、13都去掉,如果去掉后得到的新数字里依旧有4、7、13,那么就要继续删掉,直到最后的数组不存在4、7、13,它才是一个吉利的数字。例如\(1411733=>111733=>11133=>113=>1\)
特别规定,如果最后所有数字都被删掉了,就输出\(0\)
小A觉得这个枯燥的工作不适合他这样的天才,于是就把这个工作交给了你。

当然,只要你能顺利解决,小A承诺会在那篇将会震惊世界的论文的特别感谢栏上署上你的大名。

Input/Output 格式 & 样例

Input

一共\(n+1\)行。

第一行一个正整数\(n\)(\(1<=n<=100\)),表示数字个数。

接下来每行一个正整数\(x\)。

Output

一共\(n\)行。

每行一个正整数,表示输入每个\(x\)对应的答案。

Sample Input 1

5
13713
141713
1333333372589
1411733
2147483647

Sample Output1

0
11
3333332589
1
21836

数据范围

对于\(10%\)的数据,\(0<=x<=2147483647\)
对于另外的\(10%\)数据,给定的数字没有数码\(3\)
对于另外的\(10%\)数据,\(n=1\)
对于全部的数据,\(n\)(\(1<=n<=1000\)),\(1<=x<=10^L\)(\(0<=L<=10^4\))

解析

「\(1<=x<=10^L\)(\(0<=L<=10^4\))」

显而易见的高精

进而联想到字符串模拟

这道题有两个点需要注意:

  • 顺序不能乱
先执行删除4和7的操作,再执行删除13的操作
  • 在删除13时要检查是否残留
样例里有一个数据1411733
先删除4和7,得到11133
再删除13,得到113

假如只删除一次13,那么就会有残留的13出现
所以要在删除之后进行检查,
否则就需要递归,将13再次删除

代码实现

评测记录 AC

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cctype>
using namespace std;

inline string eraseAll4s(string x) {
    string ret = "";
    int len = x.length();
    for (int i = 0; i < len; ++i) if (x[i] == '4') x[i] = '-'; // 删除的'4'用'-'表示
    for (int i = 0; i < len; ++i) if (isdigit(x[i])) ret += x[i]; // 采集存留的数字,组成一个新的字符串
    return ret;
}

inline string eraseAll7s(string x) {
    // 代码思想一样,不再赘述
    string ret = "";
    int len = x.length();
    for (int i = 0; i < len; ++i) if (x[i] == '7') x[i] = '-';
    for (int i = 0; i < len; ++i) if (isdigit(x[i])) ret += x[i];
    return ret;
}

inline string eraseAll13s(string x) {
    string ret = "";
    int len = x.length();
    for (int i = 0; i < len - 1; ++i) {
        if (x[i] == '1' && x[i+1] == '3') x[i] = x[i+1] = '-';
        // 注意这里要同时检测两个字符
    }
    bool b = false;
    for (int i = 0; i < len; ++i) if (isdigit(x[i])) ret += x[i];
    for (int i = 0; i < len - 1; ++i) {
        // 重新进行检查
        if (ret[i] == '1' && ret[i+1] == '3') {
            b = true;
            break;
        }
    }
    if (b) {
        ret = eraseAll13s(ret); // 递归删除
    }
    return ret;
}

string Modify(string x) {
    string ret = "";
    ret = eraseAll4s(x);
    ret = eraseAll7s(ret);
    ret = eraseAll13s(ret);
    // 进行删除
    if (ret == "") ret = "0";
    return ret;
}

int main(int argc, char *const argv[]) {
    ios::sync_with_stdio(false);
    int n;
    string v;
    cin >> n;
    while (n --> 0) {
        /*
           这里是一个比较神奇的 while(),
           效果相当于 for (int i = 0; i < n; ++i),
           但是会对n进行修改,下标也是从n-1到0
        */
        cin >> v;
        cout << Modify(v) << endl;
    }
    return 0;
}

原文地址:https://www.cnblogs.com/handwer/p/11745315.html

时间: 2024-10-13 09:50:06

2017 国庆清北刷题冲刺班《角谷猜想》的相关文章

清北刷题冲刺 11-03 a.m

纸牌 后缀数组 巧克力

清北刷题冲刺 11-02 a.m

卖书 写代码 迷宫

清北刷题冲刺 11-02 p.m

函数最值 函数最值2 序列

清北刷题冲刺 11-03 p.m

三向城 #include<iostream> #include<cstdio> using namespace std; int n,x,y; int main(){ freopen("city.in","r",stdin);freopen("city.out","w",stdout); // freopen("Cola.txt","r",stdin); scan

2016.10.29 清北学堂NOIP冲刺班Day1 AM 考试总结

成绩:满分300,我得了200, 1:90//前两个题目都是模拟,没用到什么其他算法,第一题有可能少考虑了一点细节 2:100 3:10//感觉是个DP,但是毫无思路,只打了个普通背包,10分而已. 题目+数据:http://pan.baidu.com/s/1bpj3SR1 下面是我的代码: 这个题目中我为了得到部分分,而特别判断了几组数据. T1: 1 /* 2 以后一定要仔细读数据范围,一定要. 3 数据范围中:20%的数据,只有秒数可能不同,言外之意就是可能相同. 4 而我的程序因为没有考

清北押题班(1)

清北押题冲刺班Text1 T1 Count 问有几个无序二元组 $ (x ?, ?y) $ 满足 $ xy \equiv 1?(mod?P ) $ , $ 0 \leq x < P?, ?0 \leq y <P $ 解题思路: 你没看错,这是day1的T1,一道赤裸裸的数学题. Subtask 1:枚举 $ O(P^2) $ 个二元组,选出符合条件的,再去重: Subtask 2:可以发现模 $ P $ 意义下,一个数 x 有逆元,当且仅当 $ gcd(x, P) = 1 $ .并且如果 $

洛谷P1080 [NOIP2012提高组D1T2]国王游戏 [2017年5月计划 清北学堂51精英班Day1]

P1080 国王游戏 题目描述 恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右 手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这 n 位大臣排 成一排,国王站在队伍的最前面.排好队后,所有的大臣都会获得国王奖赏的若干金币,每 位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右 手上的数,然后向下取整得到的结果. 国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序, 使得获得奖赏最多的大

【模板】 递归线段树 [2017年五月计划 清北学堂51精英班Day4]

P3372 [模板]线段树 1 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. 第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值. 接下来M行每行包含3或4个整数,表示一个操作,具体如下: 操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k 操作2: 格式:2 x y 含义:输出区间[x,y]内每个数的

【模板】倍增LCA [2017年5月计划 清北学堂51精英班 Day3]

P3379 [模板]最近公共祖先(LCA) 题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每行包含两个正整数x.y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树). 接下来M行每行包含两个正整数a.b,表示询问a结点和b结点的最近公共祖先. 输出格式: 输出包含M行,每行包含一个正整数,依次为每一个询问的结果. 输入输出样例 输入