<更新提示>


<正文>

T1 gift

Description

​ 夏川的生日就要到了。作为夏川形式上的男朋友,季堂打算给夏川买一些生日礼物。

​ 商店里一共有种礼物。夏川每得到一种礼物,就会获得相应喜悦值Wi(每种礼物的喜悦值不能重复获得)。

​ 每次,店员会按照一定的概率Pi(或者不拿出礼物),将第i种礼物拿出来。季堂每次都会将店员拿出来的礼物买下来。没有拿出来视为什么都没有买到,也算一次购买。

​ 众所周知, 白毛切开都是黑的。 所以季堂希望最后夏川的喜悦值尽可能地高。

​ 求夏川最后最大的喜悦值是多少,并求出使夏川得到这个喜悦值,季堂的期望购买次数。

Input Format

​ 第一行,一个整数N,表示有N种礼物。

​ 接下来N行,每行一个实数Pi和正整数Wi,表示第i种礼物被拿出来的概率和可以获得喜悦值。

Output Format

​ 第一行,一个整数表示可以获得的最大喜悦值。

​ 第二行,一个实数表示获得这个喜悦值的期望购买次数,保留3位小数。

Sample Input

3
0.1 2
0.2 5
0.3 7

Sample Output

14
12.167

Hint

对于10%的数据,N = 1

对于30%的数据,N ≤ 5

对于100%的数据,N ≤ 20 ,0 < Wi ≤ 10^9 ,0 < Pi ≤ 1且∑Pi ≤ 1

解析

第一问显然是所有喜悦值的累加和,问题在于第二问买到每一种礼物的期望天数。

观察数据范围后,很容易想到是状态压缩\(dp\),但是发现样例完全不可推,于是转移的思路有点难找。

当然,状态一定是\(f[S]\)代表买到了礼物状态为\(S\)时的期望天数,那么目标状态为\(f[2^n-1]\)。考虑如何转移,显然,由于给出的概率是针对每一天拿出某个物品的概率,那么我们转移也从每一天的角度考虑:

\[f_S=\sum_{S'\cap i= S}(f_{S'}*p_i)+(1-\sum_{i\in S}p_i)f_S+1
\]

方程的含义为:对于状态\(S\),我们考虑取出物品的每一种可能,要么取到了集合中的某一个物品,要么取到了集合外的物品或没取到物品,概率乘上各自的期望再加上取这一次的\(1\)就是当前状态的期望。

将状态转移方程移项可以得到:

\[\sum_{i\in S}p_if_S=\sum_{S'\cap i=S}f_{S'}p_i+1
\]

直接计算即可。

\(Code:\)

#include<bits/stdc++.h>
using namespace std;
const int N = 21;
int n,w[N],cnt[1<<N];
double p[N],f[1<<N];
long long sum;
inline void input(void)
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%lf%d",&p[i],&w[i]),
sum += w[i];
}
inline void dp(void)
{
f[0] = 0;
for (int S=1;S<1<<n;S++)
cnt[S] = cnt[ S & (S-1) ] + 1;
for (int S=1;S<1<<n;S++)
{
double sump = 0.0;
for (int i=1;i<=n;i++)
if ( S >> (i-1) & 1 )
f[S] += p[i] * f[S^(1<<(i-1))] , sump += p[i];
f[S] = ( f[S] + 1 ) / sump;
}
}
int main(void)
{
input();
dp();
printf("%lld\n%.3lf\n",sum,f[(1<<n)-1]);
return 0;
}

通讯

Description

​ “这一切都是命运石之门的选择。”

​ 试图研制时间机器的机关SERN截获了中二科学家伦太郎发往过去的一条短信,并由此得知了伦太郎制作出了电话微波炉(仮)。

​ 为了掌握时间机器的技术,SERN总部必须尽快将这个消息通过地下秘密通讯网络,传达到所有分部。

​ SERN共有N个部门(总部编号为0),通讯网络有M条单向通讯线路,每条线路有一个固定的通讯花费Ci。

​ 为了保密,消息的传递只能按照固定的方式进行:从一个已知消息的部门向另一个与它有线路的部门传递(可能存在多条通信线路)。我们定义总费用为所有部门传递消息的费用和。

​ 幸运的是,如果两个部门可以直接或间接地相互传递消息(即能按照上述方法将信息由X传递到Y,同时能由Y传递到X),我们就可以忽略它们之间的花费。

​ 由于资金问题(预算都花在粒子对撞机上了),SERN总部的工程师希望知道,达到目标的最小花费是多少。

Input Format

​ 多组数据,文件以2个0结尾。

​ 每组数据第一行,一个整数N,表示有N个包括总部的部门(从0开始编号)。然后是一个整数M,表示有M条单向通讯线路。

​ 接下来M行,每行三个整数,Xi,Yi,Ci,表示第i条线路从Xi连向Yi,花费为Ci。

Output Format

​ 每组数据一行,一个整数表示达到目标的最小花费。

Sample Input

3 3
0 1 100
1 2 50
0 2 100
3 3
0 1 100
1 2 50
2 1 100
2 2
0 1 50
0 1 100
0 0

Sample Output

150
100
50

Hint

​ 对于10%的数据,保证M=N-1

​ 对于另30%的数据,N ≤ 20 ,M ≤ 20

​ 对于100%的数据,N ≤ 50000 ,M ≤ 10^5 ,Ci ≤ 10^5 ,数据组数 ≤ 5

​ 数据保证一定可以将信息传递到所有部门。

解析

显然,忽略花费的点一定在有向图的强连通分量里,那么只需用\(tarjan\)对原图进行\(SCC\)缩点,原问题就转化成了最小树形图问题。

这个最小树形图问题是在缩点后的\(DAG\)上的,所以可以直接对\(DAG\)执行拓扑排序,在过程中贪心选取最小边权的边即可。

\(Code:\)

#include<bits/stdc++.h>
using namespace std;
const int N = 50020 , M = 1e5+20;
struct edge{int ver,val,next;}e[M],e_[M];
int n,m,t,Head[M],dfn[N],low[N],in[N],Head_[M],t_;
int con[N],Stack[N],ins[N],top,num,cnt;
long long ans;
priority_queue < int , vector<int> , greater<int> > Heap[N];
inline void insert(int x,int y,int v)
{
e[++t] = (edge){y,v,Head[x]} , Head[x] = t;
}
inline void insert_(int x,int y,int v)
{
e_[++t_] = (edge){y,v,Head_[x]} , Head_[x] = t_;
}
inline int read(void)
{
int x = 0 , w = 0; char ch = ' ';
while ( !isdigit(ch) ) w |= ch=='-' , ch = getchar();
while ( isdigit(ch) ) x = x*10 + ch-48 , ch = getchar();
return w ? -x : x;
}
inline void input(void)
{
for (int i=1;i<=m;i++)
{
int x = read()+1 , y = read()+1 , v = read();
insert( x , y , v );
}
}
inline void Tarjan(int x)
{
dfn[x] = low[x] = ++num;
Stack[++top] = x , ins[x] = 1;
for (int i=Head[x];i;i=e[i].next)
{
int y = e[i].ver;
if ( !dfn[y] )
{
Tarjan(y);
low[x] = min( low[x] , low[y] );
}
else if ( ins[y] )
low[x] = min( low[x] , dfn[y] );
}
if ( dfn[x] == low[x] )
{
++cnt; int T = 0;
do
{
T = Stack[top--] , ins[T] = 0;
con[T] = cnt;
}
while ( x != T );
}
}
inline void rebuild(void)
{
for (int i=1;i<=n;i++)
{
for (int j=Head[i];j;j=e[j].next)
{
int x = i , y = e[j].ver;
if ( con[x] == con[y] ) continue;
insert_( con[x] , con[y] , e[j].val );
in[ con[y] ]++;
}
}
}
inline void Topsort(void)
{
queue < int > q;
for (int i=1;i<=cnt;i++)
if ( !in[i] ) q.push(i);
while ( !q.empty() )
{
int temp = q.front();
q.pop();
if ( Heap[temp].size() )
ans += Heap[temp].top();
for (int i=Head_[temp];i;i=e_[i].next)
{
int next = e_[i].ver;
in[next]-- , Heap[next].push(e_[i].val);
if ( !in[next] ) q.push(next);
}
}
}
inline void reset(void)
{
for (int i=1;i<=cnt;i++)
while ( Heap[i].size() )
Heap[i].pop();
num = cnt = top = t = t_ = 0;
ans = 0LL;
memset( Head , 0 , sizeof Head );
memset( Head_ , 0 , sizeof Head_ );
memset( dfn , 0 , sizeof dfn );
memset( low , 0 , sizeof low );
memset( in , 0 , sizeof in );
memset( ins , 0 , sizeof ins );
memset( con , 0 , sizeof con );
}
int main(void)
{
while ( scanf("%d%d",&n,&m) && n && m )
{
input();
for (int i=1;i<=n;i++)
if ( !dfn[i] ) Tarjan(i);
rebuild();
Topsort();
printf("%lld\n",ans);
reset();
}
return 0;
}

奇袭

Description

​ 由于各种原因,桐人现在被困在Under World(以下简称UW)中,而UW马上要迎来最终的压力测试——魔界入侵。

​ 唯一一个神一般存在的Administrator被消灭了,靠原本的整合骑士的力量是远远不够的。所以爱丽丝动员了UW全体人民,与整合骑士一起抗击魔族。

​ 在UW的驻地可以隐约看见魔族军队的大本营。整合骑士们打算在魔族入侵前发动一次奇袭,袭击魔族大本营!

​ 为了降低风险,爱丽丝找到了你,一名优秀斥候,希望你能在奇袭前对魔族大本营进行侦查,并计算出袭击的难度。

​ 经过侦查,你绘制出了魔族大本营的地图,然后发现,魔族大本营是一个N×N的网格图,一共有N支军队驻扎在一些网格中(不会有两只军队驻扎在一起)。

​ 在大本营中,每有一个k×k(1≤k≤N)的子网格图包含恰好k支军队,我们袭击的难度就会增加1点。

​ 现在请你根据绘制出的地图,告诉爱丽丝这次的袭击行动难度有多大。

Input Format

​ 第一行,一个正整数N,表示网格图的大小以及军队数量。

​ 接下来N行,每行两个整数,Xi,Yi,表示第i支军队的坐标。

​ 保证每一行和每一列都恰有一只军队,即每一个Xi和每一个Yi都是不一样的。

Output Format

​ 一行,一个整数表示袭击的难度。

Sample Input

5
1 1
3 2
2 4
5 5
4 3

Sample Output

10

Hint

​ 对于30%的数据,N ≤ 100

​ 对于60%的数据,N ≤ 5000

​ 对于100%的数据,N ≤ 50000

解析

由于军队的横纵坐标各不相同,所以原问题可以转换为序列问题:给定一个\(1-n\)的排列,求这个序列中有多少个子序列满足子序列中的数字恰好是连续的一串数。很容易可以知道,子区间\([l,r]\)符合要求,就会有\(max_{l,r}-min_{l,r}=r-l\),所以我们从最值入手,考虑一个分治算法。

定义分治函数\(divide(l,r)\)统计区间\([l,r]\)的答案,那么落在区间\([l,mid]\)和\([mid+1,r]\)的答案可以递归处理。问题在于统计跨过中点\(mid\)的合法子序列。我们根据最值来讨论,若最大最小值都在\(mid\)左边,那么我们可以直接枚举区间左端点,然后利用上述性质计算区间长度,得到区间右端点,在判断是否合法即可。

若最小值在\(mid\)左边,最大值在\(mid\)右边,我们可以对上述式子做一下转换:\(max_{l,r}-r=min_{l,r}-l\),那么只需将等式一边的值先塞在桶里,再枚举计算另一边的值就能累加答案。但是,可能会出现满足等式但不满足小值在\(mid\)左边,最大值在\(mid\)右边的前提条件的情况,所以我们要在满足条件的前提下加点。根据最小值的单调不增性,我们可以找到区间最右点并满足最小值在左边,根据最大值的单调不减性,我们可以找到区间最左点并满足最大值在右边,那这个区间内的任意一个点都可能成为答案的右端点,根据桶来统计即可。

当然,还有最大最小值都在\(mid\)右边,最大值在\(mid\)左边,最小值在\(mid\)右边两种情况,方法是一样的。

\(Code:\)

#include<bits/stdc++.h>
using namespace std;
const int N = 300020 , INF = 1<<30;
int n,a[N],Min[N],Max[N];
long long ans,record[2*N];
inline void input(void)
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
int x,y; scanf("%d%d",&x,&y);
a[x] = y;
}
}
inline void divide(int l,int r)
{
if ( l == r ) return;
int mid = l+r >> 1;
divide( l , mid ) , divide( mid+1 , r );
Min[mid] = Max[mid] = a[mid];
Min[mid+1] = Max[mid+1] = a[mid+1];
for (int i=mid+2;i<=r;i++)
Min[i] = min( Min[i-1] , a[i] ) , Max[i] = max( Max[i-1] , a[i] );
for (int i=mid-1;i>=l;i--)
Min[i] = min( Min[i+1] , a[i] ) , Max[i] = max( Max[i+1] , a[i] );
for (int i=mid;i>=l;i--)
{
int R = Max[i] - Min[i] + i;
if ( R > mid && R <= r && Max[R] < Max[i] && Min[R] > Min[i] ) ans++;
}
for (int i=mid+1;i<=r;i++)
{
int L = i - Max[i] + Min[i];
if ( L <= mid && L >= l && Max[L] < Max[i] && Min[L] > Min[i] ) ans++;
}
int head = mid+1 , tail = mid+1;
for (int i=mid;i>=l;i--)
{
while ( tail <= r && Min[tail] > Min[i] )
++record[ Max[tail] - tail + n ] , ++ tail;
while ( head < tail && Max[head] < Max[i] )
--record[ Max[head] - head + n ] , ++ head;
ans += record[ Min[i] - i + n ];
}
while ( head < tail )
--record[ Max[head] - head + n ] , ++ head;
head = mid , tail = mid;
for (int i=mid+1;i<=r;i++)
{
while ( head >= l && Min[head] > Min[i] )
++record[ Max[head] + head ] , -- head;
while ( tail > head && Max[tail] < Max[i] )
--record[ Max[tail] + tail ] , -- tail;
ans += record[ Min[i] + i ];
}
while ( head < tail )
--record[ Max[tail] + tail ] , -- tail;
}
int main(void)
{
input();
divide( 1 , n );
printf("%lld\n",ans+(long long)n);
return 0;
}

<后记>

『7.3 NOIP模拟赛题解』的更多相关文章

  1. 『7.5 NOIP模拟赛题解』

    T1 Gift Description ​ 人生赢家老王在网上认识了一个妹纸,然后妹纸的生日到了,为了表示自己的心 意,他决定送她礼物.可是她喜爱的东西特别多,然而他的钱数有限,因此他想 知道当他花一 ...

  2. 大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程

    数据 http://files.cnblogs.com/htfy/data.zip 简要题解 桌球碰撞 纯模拟,注意一开始就在袋口和v=0的情况.v和坐标可以是小数.为保险起见最好用extended/ ...

  3. 10.6-10.7 牛客网NOIP模拟赛题解

    留个坑... upd:估计这个坑补不了了 如果还补不了就删了吧

  4. NOIP第7场模拟赛题解

    NOIP模拟赛第7场题解: 题解见:http://www.cqoi.net:2012/JudgeOnline/problemset.php?page=13 题号为2221-2224. 1.car 边界 ...

  5. contesthunter暑假NOIP模拟赛第一场题解

    contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...

  6. 队爷的讲学计划 CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的讲学计划 题解:刚开始理解题意理解了好半天,然后发 ...

  7. 队爷的Au Plan CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的Au%20Plan 题解:看了题之后觉得肯定是DP ...

  8. 队爷的新书 CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的新书 题解:看到这题就想到了 poetize 的封 ...

  9. CH Round #58 - OrzCC杯noip模拟赛day2

    A:颜色问题 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2358%20-%20OrzCC杯noip模拟赛day2/颜色问题 题解:算一下每个仆人到它的目的地 ...

随机推荐

  1. CTF-代码审计(3)..实验吧——你真的会PHP吗

    连接:http://ctf5.shiyanbar.com/web/PHP/index.php 根据题目应该就是代码审计得题,进去就是 日常工具扫一下,御剑和dirsearch.py 无果 抓包,发现返 ...

  2. maven 学习---Maven教程

    Apache Maven是一个软件项目管理和综合工具.基于项目对象模型(POM)的概念,Maven可以从一个中心资料片管理项目构建,报告和文件. 本教程将介绍如何使用Maven在Java开发,或任何其 ...

  3. angular6 页面加载数据时的loading提示

    使用npm安装ngx-loading模块 npm install --save ngx-loading 在app.module.ts中导入模块 import { BrowserModule } fro ...

  4. Linux的DNS正向解析部署

    前面介绍了DNS的作用及其相关的结果.Linux服务之DNS介绍 下面开始有关DNS的服务部署.<DNS正向解析示例> 工具:虚拟机 centos7 配置:Linux   IP 192.1 ...

  5. 团队第五次作业:alpha2成绩汇总

    一.作业题目 团队第五次作业:alpha2发布 二.作业评分标准 博客评分规则(总分100)博客要求 给出开头和团队成员列表(10') 给出发布地址以及安装手册(20') 给出测试报告(40') 给出 ...

  6. mysql binlog空间维护

    默认情况下,mysql主从同步的binlog日志,会一直保存. 对于如果已同步好的数据,这显然比较浪费资源. 且如果生产环境磁盘太小,随时还会爆掉,所以很有必要作好binlog的空间维护. 以下操作, ...

  7. js数组sort()排序的问题

    最近跟自以为很了解的数组干上了,就像许多我们认知的东西一样,总以为自己很了解的东西,其实并不了解. var a=[12,4,1,43,5,3,52];  alert(a);   //源:12,4,1, ...

  8. python接口自动化框架

    接口测框架 安装教程 需要3.5及以上版本的python pip install -r requirements.txt 使用说明 运行manage.py创建项目 创建的项目在projects目录下 ...

  9. 3-OpenResty 配置PHP

    由于咱以前是用PHP做的东西,又不想重新用 OpenResty自带的编写,所以呢咱设置下,可以像以前Apache那样访问PHP文件 首先去下载 PHP https://windows.php.net/ ...

  10. SFTP 文件上传下载工具类

    SFTPUtils.java import com.jcraft.jsch.*; import com.jcraft.jsch.ChannelSftp.LsEntry; import lombok.e ...