A.ICPC Penalty
按题意模拟即可
(一个血的教训:判断字符串是那种可以只判断第一个字母(如果没有重复,否则全打打错了就寄了,某人Unknown打错过)
s = input()
n, t = map(int, input().split())
if s[0] == "A":
print((n-1)*20+t)
else:
print(0)
B.小苯的无限数组
显然每次操作后 会变为
。
答案即为 。
for _ in range(int(input())):
n, k = map(int, input().split())
print(n*(1<<k))
C.小苯的真假游戏
由于是环形的,不难想到最多只有两种答案。
设 为上一个人说真假的情况。若
为
, 则
不变;若
为
,则
翻转(
)。
因此整个过程中 会翻转
(字符串中
的个数) 次。要合法必须满足转一圈后
不变,因此
必须为偶数。
for _ in range(int(input())):
n = int(input())
s = input()
if s.count("0") % 2 == 0:
print(2)
else:
print(0)
D. 小苯的区间选数2.0
经典贪心题。
按左端点排序后,对于当前 将所有左端点小于其的区间的右端点插入优先队列中,在从中取出至少为
的最小数字即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define fi first
#define se second
int main(){
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t;cin>>t;
while(t--){
ll n;cin>>n;
vector<pair<ll, ll>> memo(n);
for(ll i=0;i<n;i++) cin>>memo[i].fi>>memo[i].se;
sort(memo.begin(), memo.end());
priority_queue<ll, vector<ll>, greater<ll>> pq;
ll mex = 0, idx=0;
while(1){
while(idx<n&&memo[idx].fi<=mex){ // 添加所有左端点 <= mex 的区间
pq.push(memo[idx].se);
idx++;
}
while(pq.size()&&pq.top()<mex) pq.pop();// 选取右端点 >= mex 的最小右端点
if(pq.empty()) break; // 如果没有右端点了,意味着枚举完了,退出循环
pq.pop();
mex++;
}
cout<<mex<<'\n';
}
}
E.小苯的GCD疑问1.0
结论题:最优解即为选取所有数字。
证明:
-
区间长度为
时,显然必须选择所有数字。
-
区间长度不为
时,最优解为选择所有数字,此时
。
时,由于最大值被删去,所有选择的数字 *
< 从选择的数字出发连续
个数字的和。
以 为例。
若 ,即为选取所有数字, 有贡献的数字为
。
若 ,有贡献的数字为
,对于
,
,
同理。
若 , 有贡献的数字为
,对于
,
。
以此类推可以发现 的方案总是小于
的情况。
求和公式 回答即可。
鞭尸
本题答案可以到 , 有人试图
或者
是会爆精度的喵~。
例如 ,
。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define fi first
#define se second
int main(){
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t;cin>>t;
while(t--){
ll l, r, k;cin>>l>>r>>k;
cout<<(l+r-1)*(r-l)/2<<'\n';
}
}
F.小苯的GCD疑问2.0
注意由于最大值没有去掉, 的结论不适用
数论分块板题。
显然我们会选取尽可能多的 相同的数字。
对于选取数字数量相同的 区间
,显然此时选择
的答案最大。
于是分块选取每个右端点, 枚举即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define fi first
#define se second
int main(){
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t;cin>>t;
while(t--){
ll n, k;cin>>n>>k;
ll l = 1;
ll ans = 0;
while(l <= n){
ll r = min(n, n/(n/l));
ll cnt = n/l;
if(cnt < k) break;
ans = max(ans, (r + cnt*r) * cnt/2 * r);
l = r + 1;
}
cout<<ans<<'\n';
}
}

京公网安备 11010502036488号