京东2022.9.3笔试三题

找数字N最小的因数q使得q*q>N.
想法:从N的开方开始遍历到N,找到符合条件就输出。

题目描述
小红拿到了一个数组,她每次可以进行如下操作之一:
选择一个元素x,将其分裂为1和x-1。
·选择一个元素x,将其分裂为a和b,需要保证a*b=x
小红希望用最少的操作次数,将所有数组的所有元素全部变成1。你能帮帮她吗?
输入描述:
第一行输入一个正整数n,代表数组的长度。
第二行输入n个正整数ai,代表小红拿到的数组。
1 ≤ n, ai ≤ 1e5
输出描述:
一个整数,代表最小的操作次数。
 
input:
2
2 6
 
output:
5

思路:将输入的数组存成vec,同时将其中最大的元素bignum找出来,然后创建一个长度为bignum+1的dp数组,将0-bignum对应的需要拆分的最小次数以动态规划的方式从小到大全填上,然后遍历一遍vec每次从dp中找出对应的需要拆分的次数加上就行了。
代码:

#include <bits/stdc++.h>
using  namespace std;
int main(){
    int n;
    cin >>n;
    vector<int> vec(n);
    for(int i=0;i<n;i++){
        cin >> vec[i];
    }
    int bignum = *max_element(vec.begin(),vec.end());
    vector<int> dp(bignum+1,0);
    dp[2] = 1;
    for(int i=3;i<=bignum;i++){
        dp[i] = dp[i-1] +1;//这是选择每次分裂-1的情况
        for(int x = 2;x< sqrt(i);x++){//从2到根号i找有没有因数相乘的方案需要的次数更少
            if(i%x == 0) {
                dp[i] = min(dp[i], dp[i / x] + dp[x] + 1);
            }
        }
    }
    int ans = 0;
    for(int i=0;i<n;i++){
        ans += dp[vec[i]];
    }
    cout << ans<<endl;
    return 0;
}


题目描述
定义一个括号串的权值为,它的最长合法括号子序列的长度。
例如,"())())的权值是4,它的最长合法括号子序列为"()()”
现在求一个给定括号串的所有子串权值之和。
输入描述:
一个仅包含'('和')'的字符串,长度不超过2e5。
输出描述:
所有子串的权值和。
 
input:
())())
 
output:
26
 
解释:
权值为2的子串有2个
权值为4的子串有2个

代码:

int main(){
    string s;
    cin >>s;
    int len = s.size();
    stack<int> st;
    int ans = 0;
    for(int i=0;i<len;i++){
        if(s[i] == '('){
            st.push(i);
        }else if(!st.empty()){
            //假设左括号左边有n个数字,那么左边其实有(n+1)种选择——什么都不选、选1个、选2个、选3个...因为要求是连续子串,所以只能有(n+1)种选择,右侧同理。两边选择的方案数需要乘起来。
            cout << 2*(st.top() +1)*(len-i)<<endl;
            ans += 2*(st.top() +1)*(len-i);
            st.pop();
        }
    }
    cout << ans <<endl;
    return 0;
}

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值