找数字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;
}