从入门到头秃周末休闲赛5

这场白给了做了4道题

在这里插入图片描述

不过据说这场的题比上一场难2333

A - 最少乘法次数

题目

给你一个非零整数,让你求这个数的 nn 次方,每次相乘的结果可以在后面使用,求至少需要多少次乘。如 2 4 : 2 × 2 = 2 2 2^4:2 \times 2=2^2 24:2×2=22(第一次乘),
2 2 × 2 2 = 2 4 2^2 \times 2^2=2^4 22×22=24 (第二次乘),所以最少共 2 次。

输入格式
第一行 mm 表示有 m ( 1 ≤ m ≤ 100 ) m ( 1 ≤ m ≤ 100 ) m(1 \le m \le 100)m(1≤m≤100) m(1m100)m(1m100) 组测试数据。

每一组测试数据有一整数 n ( 0 < n ≤ 10000 ) n ( 0 < n ≤ 10000 ) n(0<n \le 10000)n(0<n≤10000) n(0<n10000)n(0<n10000)

输出格式
输出每组测试数据所需次数 s。

输出时每行末尾的多余空格,不影响答案正确性

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

思路

类似于快速幂的思路 把一个数按照二进制展开,先把首位应该乘的次数算出来,然后从最后一位到首位中间所有的数就都能用来做乘法了。然后再算一下后面各位需要乘法的次数(每次遇到一个1就+1)统计完就是最小的次数。

代码

#include <cstdio>
#include <string>
#include <cstring>
using namespace std;
const int maxn = 10000+10;
int ans[maxn];
int qpow(int a,int b)
{
    int ans=1,cnt=0;
    int base = a;
    while(b)
    {
        if(b&1)
        ans *= base,cnt++;
        base*=base;
        b>>=1;
    }
    return cnt-1;
}
int main()
{
    int m,n;
    scanf("%d",&m);
    while(m--)
    {
        scanf("%d",&n);
        int x = n;
        int ans=0;
        while(x)
        {
            x/=2;
            ans++;
        }
        ans--;
        // printf("%d %d %d\n",ans,ans,ans);
        printf("%d\n",ans+qpow(2,n));
    }
}

B - 完美字符串

题目

约翰认为字符串的完美度等于它里面所有字母的完美度之和。每个字母的完美度可以由你来分配,不同字母的完美度不同,分别对应一个1-26之间的整数。

约翰不在乎字母大小写(也就是说字母A和a的完美度相同)。给定一个字符串,输出它的最大可能的完美度。例如:dad,你可以将26分配给d,25分配给a,这样整个字符串完美度为77。

Input
输入一个字符串S(S的长度 <= 10000),S中没有除字母外的其他字符。
Output
由你将1-26分配给不同的字母,使得字符串S的完美度最大,输出这个完美度。
Sample Input
dad
Sample Output
77

思路

贪心 出现次数最多的分的权值也最大。

代码

#include <map>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
map<char,int>mp;
int ans[27];
int main()
{
    string s;
    cin>>s;
    int len = s.size();
    for(int i=0;i<len;i++)
    s[i]=tolower(s[i]);
    for(int i=0;i<len;i++)
    mp[s[i]]++;
    for(int i=0;i<26;i++)
    ans[i]=mp['a'+i];
    // for(int i=0;i<26;i++)
    // printf("%d ",ans[i]);
    sort(ans,ans+26,greater<int>());
    int now = 26;
    long long sum=0;
    for(int i=0;ans[i];i++)
    {
        sum+=now * ans[i];
        now--;
    }
    printf("%lld\n",sum);
}

上来没注意大消息还wa了一次- -

C - 集合操作

题目

现有一整数集(允许有重复元素),初始为空。我们定义如下操作:
add x \text{add x} add x 把 x加入集合
del x \text{del x} del x 把集合中所有与 x 相等的元素删除
ask x \text{ask x} ask x对集合中元素x的情况询问

对每种操作,我们要求进行如下输出。
add \text{add} add 输出操作后集合中 x 的个数
del \text{del} del输出操作前集合中 x 的个数
ask \text{ask} ask先输出 00 或 11 表示 x 是否曾被加入集合(00 表示不曾加入),再输出当前集合中 x 的个数,中间用空格格开。

输入格式
第一行是一个整数 n,表示命令数。 0 ≤ n ≤ 1000000 ≤ n ≤ 100000 0 \le n \le 1000000≤n≤100000 0n1000000n100000。后面 n n n 行命令,如 Description \text{Description} Description中所述。

输出格式
共 n 行,每行按要求输出。

输出时每行末尾的多余空格,不影响答案正确性

样例输入
7
add 1
add 1
ask 1
ask 2
del 2
del 1
ask 1
样例输出
1
2
1 2
0 0
0
2
1 0

思路

用一个set 和multiset来操作。
1.用set来记录当前的数是否加入过集合。
2.删除的时候直接用multiset的erase操作就可以清除所有的x。
3.ask的时候在set里面找,如果能找到的话就输出1和数量,找不到说明
之前没有加入过集合,那么输出0 0

代码

#include <set>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
char s[4];
int main()
{
    multiset<int>mst;
    set<int>st;
    set<int>::iterator it;
    int n,x;
    scanf("%d",&n);
    while(n--)
    {
        scanf("%s",s);
        scanf("%d",&x);
        if(s[1]=='d')
        {
            st.insert(x);
            mst.insert(x);
            printf("%d\n",mst.count(x));
        }
        else if(s[1]=='s')
        {
            it = st.find(x);
            if(it==st.end())
            {
                printf("%d %d\n",0,0);
            }
            else
            {
                int ans = mst.count(x);
                printf("%d %d\n",1,ans);
            }
        }
        else if(s[1]=='e')
        {
            printf("%d\n",mst.count(x));
            mst.erase(x);
        }
    }
}

D - 大数乘法

题目

给出2个大整数A,B,计算A*B的结果。
Input
第1行:大数A 第2行:大数B (A,B的长度 <= 1000,A,B >= 0)
Output
输出A * B
Sample Input
123456
234567
Sample Output
28958703552

思路

用的java 傻了


import java.io.BufferedInputStream;
import java.math.BigInteger;
import java.util.Scanner;

public class Main{
	public static void main(String[] args) {
		Scanner cin = new Scanner(new BufferedInputStream(System.in));
		BigInteger a = cin.nextBigInteger();
		BigInteger b = cin.nextBigInteger();
		System.out.println(a.multiply(b));
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值