牛客小白月赛32
拼三角
枚举合法方案
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 10;
int n;
ll a[N];
void work()
{
do
{
if (a[0] + a[1] > a[2]
&& a[0] + a[2] > a[1]
&& a[1] + a[2] > a[0]
&& a[3] + a[4] > a[5]
&& a[3] + a[5] > a[4]
&& a[4] + a[5] > a[3]
)
{
puts("Yes");
return;
}
}while (next_permutation(a, a + 6));
puts("No");
}
int main()
{
cin >> n;
while (n -- )
{
for (int i = 0; i < 6; i ++ ) cin >> a[i];
sort(a, a + 6);
work();
}
return 0;
}
相对分子质量
栈的模拟
每次遇到(我们就往栈里面放入一个-1表示这里有一个左括号,然后,我们对括号内的内容处理。
如果是英文字母,就将这个化学元素的相对原子质量放入栈中,如果遇到的是数字,那么我们就把前面栈中的元素取出来,乘上它,
因为数字前面要么是化学元素要么是括号,都是要呈上这个数字的。如果遇到了右括号,就将栈中左括号前的所有元素加起来。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
unordered_map<string, ll> mp;
stack<ll> st;
int main()
{
ll n, m, k;
string s;
cin >> m >> n;
for (ll i = 1; i <= m; i ++ )
{
cin >> s >> k;
mp[s] = k;
}
while (n -- )
{
cin >> s;
ll n = s.size();
string t;
for (ll i = 0; i < n; i ++ )
{
if (s[i] == '(') st.push(-1);
else if (s[i] == ')')
{
ll x = 0;
while (st.top() != -1) x += st.top(), st.pop();
st.pop();
st.push(x);
}
else if (s[i] >= '0' && s[i] <= '9')
{
ll x = 0;
bool sign = 0;
while (s[i] >= '0' && s[i] <= '9') x = x * 10 + s[i ++ ] - '0', sign = 1;
ll y = st.top();
st.pop();
st.push(y * x);
i -= sign;
}
else
{
t = s[i];
i ++;
while (islower(s[i]) && i < n) t += s[i ++ ];
i --;
st.push(mp[t]);
}
}
ll x = 0;
while (st.size()) x += st.top(), st.pop();
cout << x << '\n';
}
return 0;
}
消减整数
我们的减数是1, 2, 4, 8,…, 2^k,这样类型的。
我们仔细观察性质,减数的增加是一倍一倍的增加的,不会存在断层式增加。
所以,我们就可以发现,每个减数最多只会使用2次,因为如果使用三次或以上。为什么呢,我们拿3举例,我们可以将一个当前减数保留下来,另外两个就凑成了下一个减数。
我们将数n化为2进制看,如果当前位为1的话,说明可以直接减去这一位的减数,如果为0的话,说明可以由两个前一个减数组合而成。
#include <cstdio>
#include <iostream>
using namespace std;
typedef long long ll;
ll n;
void work()
{
cin >> n;
int cnt = 0, m = 1;
while (n > 0)
{
if (n & m)//二进制最高位为1,其他为0
{
cnt ++;
n -= m;
}
else
{
cnt += 2;
n -= m << 1;
}
m <<= 1;
}
cout << cnt << '\n';
}
int main()
{
int T; cin >> T;
while (T -- )
{
work();
}
return 0;
}
或者我们可以这么想,我们要尽可能每次减去最大的减数才好,那么我们算的最大的减数,然后当前数减去最大的减数后,将他的二进制中1的个数求出来就OK了。
#include <cstdio>
#include <iostream>
using namespace std;
typedef long long ll;
ll n;
ll s[50];
void init()
{
s[0] = 1;
for (int i = 1; i <= 31; i ++ )
{
s[i] = s[i - 1] + (1 << i);
// cout << s[i] << endl;
}
}
void work()
{
ll n; cin >> n;
int now = 0, cnt = 0;
for (int i = 30; i >= 0; i -- )
{
if (s[i] <= n)
{
now = i;
// cout << s[i] << ' ' << i << endl;
break;
}
}
// cout << "==========" << now << endl;
cnt += now + 1;
n -= s[now];
while (n)
{
if (n & 1) cnt ++;
n >>= 1;
}
cout << cnt << '\n';
}
int main()
{
init();
int T; cin >> T;
while (T -- )
{
work();
}
return 0;
}