A层邀请赛5
A层邀请赛5
A 赤
我不会二分,但是这个题他是二分套二分。。。。
首先不难搞到一个的
定义表示前只猫,用了个第一种零食,个第二种零食的捕获的猫的期望,转移考虑当前猫用哪些零食
如何优化这个?
我们想能不能砍掉一维,显然砍不掉,,形式相同
我们尝试砍掉
砍掉之后,直接显然会超出限制,用什么方法能够让选择更多第二种零食不是越多越优秀呢?
可以发现,如果每选一个都给期望减去一个值,那么选第二种零食就不是越多越好
这令我们想到那个题,那么这个题是否可以二分?
以横轴为选择第二种零食的数量,纵轴为期望,由于我们每次选取最优策略,所以斜率单调不增,这是一个上凸包!可以二分
二分,时每选择一个第二种零食就减去一个,同步处理使用第二种零食的数量,最后撤掉的贡献,根据数量调整二分区间,(其实是改变斜率,不停的切凸包)
于是我们可以砍掉一维,复杂度变成但是还是过不了
继续优化,我们上面提到,形式相同,那么能砍掉,为什么不能?
砍掉以后,以同样的方式处理,每一次的二分都重新二分
这样我们就有了二分套二分的的优秀做法
code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 100003;
int n, a, b;
double pa[maxn], pb[maxn], pab[maxn];
double f[100005], ca[100005], cb[100005];
typedef pair<int, int> pii;
pii solve(double mid, double mid2){
for(int i = 1; i <= n; ++i){
f[i] = f[i - 1];
ca[i] = ca[i - 1];
cb[i] = cb[i - 1];
if(f[i] < f[i - 1] + pa[i] - mid){
f[i] = f[i - 1] + pa[i] - mid;
ca[i] = ca[i - 1] + 1;
cb[i] = cb[i - 1];
}
if(f[i] < f[i - 1] + pb[i] - mid2){
f[i] = f[i - 1] + pb[i] - mid2;
ca[i] = ca[i - 1];
cb[i] = cb[i - 1] + 1;
}
if(f[i] < f[i - 1] + pab[i] - mid - mid2){
f[i] = f[i - 1] + pab[i] - mid - mid2;
ca[i] = ca[i - 1] + 1;
cb[i] = cb[i - 1] + 1;
}
}
return pii(ca[n],cb[n]);
}
int main(){
while(~scanf("%d%d%d",&n, &a, &b)){
for(int i = 1; i <= n; ++i)scanf("%lf",&pa[i]);
for(int i = 1; i <= n; ++i)scanf("%lf",&pb[i]);
for(int i = 1; i <= n; ++i)pab[i] = pa[i] + pb[i] - pa[i] * pb[i];
double l = 0, r = 1, mid, ll = 0, rr = 1, midd;
for(int i = 1; i <= 50; ++i){
mid = (l + r) / 2;
ll = 0, rr = 1;
for(int i = 1; i <= 50; ++i){
midd = (ll + rr) / 2;
if(solve(mid, midd).second > b)ll = midd;
else rr = midd;
}
if(solve(mid, rr).first > a)l = mid;
else r = mid;
}
solve(r, rr);
printf("%lf\n",f[n] + r * a + rr * b);
}
return 0;
}
B Tourist Attractions
首先暴力或者枚举有
正解也是枚举,但是有优化
枚举中间两个点,计算贡献,减去非法贡献
非法贡献是什么,显然是构成了三元环,那么我们把他俩的与一下,减去即可
大法好,可惜我不会
code
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<bitset>
using namespace std;
const int maxn = 1505;
int n;
long long ans = 0;
bitset <maxn> b[maxn];
char c[maxn];
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; ++i){
scanf("%s",c + 1);
for(int j = 1; j <= n; ++j)
if(c[j] == '1')b[i][j] = 1;
}
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= n; ++j){
if(b[i][j] == 0)continue;
int r1 = b[i].count() - 1;
int r2 = b[j].count() - 1;
int r3 = (b[i]&b[j]).count();
ans += r1 * r2 - r3;
}
}
printf("%lld\n",ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】