3.28 做做看6 题解

问题 A: 一无所有

时间限制: 1 Sec 内存限制: 128 MB
题目描述
kk穷的只剩下钱,但是她却很不喜欢这种感觉,这都只是数字,所以她希望让自己一无所有,把数字变为0

她现在有一种花钱方式:

每一步有两种选择:1. 让数字减一   
			   2.将数字整除k 当数字能够整除k时

她需要你帮她计算需要多少步,才能变为0

输入
有t组输入样例,每组输入样例包括 数字 n 和 k ( 2 <= n <= 10^18, 2 <= k <= 10 ^ 18)
输出
对于每组输入样例,输出其变为0 所需步数
样例输入
3
99 4
59 7
77 6
样例输出
9
7
9

思路:将题目转化下,就可以知道大概思路,我们都知道,当除以任何大于1的正整数,数据减小的速度都会大于直接减1的速度,那么也就转化成了一个简单的贪心问题,如果能够整除k,就将n去除以k,不能的话,减到能够整除的k的数字,然而一次次减完再去判断会耗费很多时间,此处我们可以考虑采用求模的方式,模数放在我们小学的时候其实就是余数,多余的数字,整数倍的多余数字,也就是说,将n减去这个多余的数字,就是距离n最近的一个k的整数倍,n = m * k + a, 则 n - a = m * k. 那么这个a就是我们所需要减去的数字,即减去a次的1,操作数+a,然后整除k,操作数+1
当然,记住不要输出多余的东西,比如什么“请输入数字n:”、“数据不规范请重新输入” 这是交互端需要做的事,运算中不需要
代码如下:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long ll;
int main()
{
    ll n, k;
    int T;
 
    scanf("%d", &T);
    ll ans;
    while (T--) {
        ans = 0;
        scanf("%lld %lld", &n, &k);
        while (n) {
            if (n % k == 0) {
                while (n % k == 0) {
                    n /= k;
                    ans++;
                }
            }else {
                ans += (n % k);
                n -= (n % k);
            }
        }
        printf("%lld\n", ans);
    }
    return 0;
}

问题 B: 塑性

时间限制: 1 Sec 内存限制: 128 MB
题目描述
现在来玩一个游戏,当有x,y且x > y 存在 x 减去素数p(p可任意选择)任意次后 有x == y 则证明其有塑性

如果有塑性则输出YES 否则输出NO

注意 1 不是素数

输入
有 T 行数据 ( 1 <= T<= 100)

每行输入 x 和 y ( 0 < y < x <= 10 ^ 18)

输出
如果符合条件,输出YES, 否则输出NO
样例输入
2
42 32
41 40
样例输出
YES
NO

思路:转化下题目意思,即(x - y)是否是一个素数的整数倍,根据素数的性质,素数是只有被1和本身整除的整数,那么素数肯定是自身的整数倍,然后合数的性质为可以被除了1和本身之外的数字整除,那么我们往下递归思考,任何合数都存在除了1和本身外的因子,若存在素因子,那么其是素数的整数倍,若存在合因子,合因子再次拆分,将会拆分到只有素因子的情况,那么合因子也是素因子的整数倍,所以合数一定是一个素数的整数倍,当然欧拉筛法的原理也证明的这点,所以说,任意大于1的数字都是某个素数的整数倍。1不是素数,而它也只是1的整数倍,所以不存在塑性(我编的性质,别当真)
然后说下常见的判断素数法,不适用这题,不管是暴力还是优化的判断法,或者说是筛法,会出现超时或者超内存的情况,当数据在10^18时,判断一个素数在优化方法下会在1s以上,而筛法在打超过八位数的表的时候会将内存和时间都超了,所以也不太适用。
代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <ctype.h>
#include <cstdlib>
#include <iostream>
#include <string>
#include <stack>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <list>
typedef long long LL;
using namespace std;
#define mem(a) memset(a, 0, sizeof a)
int main()
{
    int T;
  
    cin >> T;
    while (T--) {
        LL a, b;
        cin >> a >> b;
        LL sub = a - b;
        if (sub == 1) {
            cout << "NO" << endl;
        }else cout << "YES" << endl;
    }
    return 0;
}

问题 C: 努力向上的计算姬

时间限制: 1 Sec 内存限制: 128 MB
题目描述
计算姬是一个的努力向上的好孩子,她在学习的课余时间,想试一试循环的计算,但是刚刚学会操作的她发现自己对底层运算的了解变得很浅。

所以她找来了你,希望你能编写一个程序,来模拟循环计算的结果。

但是夜深了,计算姬表示很困,所以她不想算太大的数字,于是她决定超过一千万的数字她就罢工(包括一千万)!!!

当她罢工的时候会输出"Go Out!!!".

现在需要你去编写一个程序,有三条命令:

  1. for循环的开头 f ,后带一个数字n,表示循环次数(0 < n <= 100)

2.for循环终止语句e,表示循环终止,每一个f 对应一个 n

  1. 自增指令,+,遇到使其加1

初始 x 为0

输入
第一行一个数字n, ( 0 < n <= 100)

第二行到第n + 1 行,每一行一个指令

输出
输出最终x的结果,如果x >= 10000000 输出"Go Out!!!"
样例输入
9
+
f 43
e
f 10
f 15
+
e
+
e
样例输出
161
提示
可能会造成 int 上溢
思路:
这题就是一道很普通的模拟题,用栈记录下之前每层循环的次数,遇到+时将循环次数总和加到答案中,如果当前总和超过10000000,那么退出运算

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <map>
#include <queue>
#include <cstring>
#include <cmath>
#include <stack>
#include <string>
using namespace std;
typedef long long ll;
string a[120000];
int num[120000];
stack<ll> s;
int main()
{
    map <string, int> mp;
 
    mp["+"] = 0;
    mp["f"] = 1;
    mp["e"] = 2;
    int n;
    ll k = 1LL * 10000000;
    scanf("%d", &n);
    memset(num, 0, sizeof num);
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
        if (mp[a[i]] == 1) cin >> num[i];
        // cout << a[i] << " " << num[i] << endl;
    }
    ll x = 0;
    ll tem = 1;
    // bool flag = false;
    bool flag_x = false;
    // cout << n << endl;
    for (int i = 0; i < n; ++i) {
        if (mp[a[i]] == 0 ) {
            if (s.empty()) x += 1;
            else x += s.top();
        }
        // cout << n << endl;
        if (mp[a[i]] == 1) {
            if (s.empty()) tem = 1;
            else tem = s.top();
            tem *= num[i];
            if (tem > k) s.push(k + 1);
            else s.push(tem);
        }
        // cout << n << endl;
        if (mp[a[i]] == 2) {
            s.pop();
        }
        if (x > k) {
            flag_x = true;
            break;
        }
        // printf("%I64d %I64d %d\n", x, tem, top);
    }
    // std::cout << "1" << '\n';
    if (flag_x) printf("Go Out!!!\n");
    else printf("%lld\n", 1LL * x);
    return 0;
}

三道题都来自 codeforce 的div2 AB ,前两题考察思维(A),最后一道属于数据结构范畴

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值