10.1综合强化刷题 Day5
T1 拼不出的数
lost.in/.out/.cpp
【问题描述】
3 个元素的集合{5; 1; 2}的所有子集的和分别是0; 1; 2; 3; 5; 6; 7; 8。发
现最小的不能由该集合子集拼出的数字是4。
现在给你一个n 个元素的集合,问你最小的不能由该集合子集拼出的
数字是多少。
注意32 位数字表示范围。
【输入格式】
第一行一个整数n。
第二行n 个正整数ai,表示集合内的元素。
【输出格式】
一行一个整数答案。
【样例输入】
3
5 1 2
【样例输出】
4
【数据规模和约定】
对于30% 的数据,满足n <=15。
对于60% 的数据,满足n <=1000。
对于100% 的数据,满足n <=100000; 1<= ai <=109。
考场中没有看到1<=ai<=10^9,认为a一定是在n的范围内的,然后完美的开了三个1000的数组,然后就崩溃了、、
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 110000
#define LL long long
using namespace std;
LL n,a[N],tot;
bool vis[N],vist[N];
LL read()
{
LL x=,f=; char ch=getchar();
') ch=getchar();
+ch-',ch=getchar();
return x*f;
}
void dfs(int now,int s,int sum)
{
if(now==s)
{
vist[sum]=;
return ;
}
;i<=n;i++)
{
if(vis[i]) continue;
vis[i]=;
dfs(now+,s,sum+a[i]);
vis[i]=;
}
}
int main()
{
// freopen("lost1.in","r",stdin);
// freopen("lost.out","w",stdout);
n=read();
;i<=n;i++) a[i]=read(),tot+=a[i];
;i<=n;i++)
dfs(,i,);
;i<=tot+;i++)
{
if(vist[i]) continue;
printf("%lld",i);
;
}
}
考场暴零代码
一个思路题吧、、(代码很短)
我们读入所有的a以后先对其进行一个sort排序,然后我们在观察我们排序后的a数组,我们可以知道当前面的前缀和加1不等于当前数,那么这个前缀和加1,就是我们要求的最小的不能被拼出的数。
正确性证明??
我们来看一组数 12 14 5 6 21 7 1 2 4 13 我们将这一组数排完序以后将会变成 1 2 4 5 6 7 12 13 14 21
假设我们不存在1这个数,那么我们最初拼出的数为2,那么1一定是不会被频出的最小的数,也就是结果。然后我们看当前数组,1跟2能拼成1 、2、 3我们判断当前前缀和也就是最大能拼出的数+1以后是否大于等于当前数,我们继续往下走3+4=7,现在用这些数我们可以拼出1~7内的所有的数,然后在判断3+4+5+6+7+12+13+14=64这样的话我们最小的不能拼成的数为64+1=65.
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 100010
#define LL long long
using namespace std;
int n,a[N];
int read()
{
,f=; char ch=getchar();
;ch=getchar();}
+ch-',ch=getchar();
return x*f;
}
int main()
{
n=read();
;i<=n;i++) a[i]=read();
sort(a+,a++n); LL sum=;
;i<=n;i++)
<a[i]) {printf(); ;}
else sum+=a[i];
printf();
;
}
AC代码
T2 整除
题目描述
给定整数n,问⌊n/i⌋ 的结果有多少个不同的数字。1<=i<=n,i 为整
数。)
比如n=5 时,⌊5/1⌋ = 5,⌊5/2⌋ = 2,⌊5/3⌋ = 1,⌊5/4⌋ = 1,⌊5/5⌋ = 1,所以结果一共有三个不同的数字。
注意32 位整数的表示范围。
输入输出格式
输入格式:
一行一个整数n。
输出格式:
一行一个整数答案。
输入输出样例
5
3
说明
对于30% 的数据,满足1 <=n <= 10^3。
对于60% 的数据,满足1 <= n <=10^12。
对于100% 的数据,满足1 <=n <=10^18。
打表找规律80分
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
LL n,ans,tot,sum;
LL read()
{
LL x=,f=; char ch=getchar();
') ch=getchar();
+ch-',ch=getchar();
return x*f;
}
int main()
{
freopen("div.in","r",stdin);
freopen("div.out","w",stdout);
tot=;n=read();
;};
) {puts(;};
while(sum<n)
{
ans++;
==) sum=sum+tot;
else sum=sum+tot,tot++;
}
) ans=;
printf("%lld",ans);
;
}
80分代码
打表找规律,我们打一个表出来以后会发现一个规律,每一个数的结果与根号n有一个比较密切的联系
我们先打一个10以内的表
| n | ans | 根号n | |
| 1 | 1 | 1 | 1*2-1=1 |
| 2 | 2 | 1 | 1*2=2 |
| 3 | 2 | 1 | 1*2=2 |
| 4 | 3 | 2 | 2*2-1=3 |
| 5 | 3 | 2 | 2*2-1=3 |
| 6 | 4 | 2 | 2*2=4 |
| 7 | 4 | 2 | 2*2=4 |
| 8 | 4 | 2 | 2*2=4 |
| 9 | 5 | 3 | 2*3-1=5 |
通过上面的表,我们是不是可以发现这样一个小规律,每一个数的开跟*2或*2-1跟我们的答案有着密切的联系。我们还可以发现当一个数的跟n等于n/跟n,也就是说我们拼出来的两个数是一样的时候我们要对最终答案-1
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
long long n,ans;
long long read()
{
,f=; char ch=getchar();
; ch=getchar();}
+ch-',ch=getchar();
return x*f;
}
int main()
{
n=read();
ans=sqrt(n);
-;
;
printf("%lld",ans);
}
AC代码
T3 钻石
题目描述
你有n 个“量子态” 的盒子,每个盒子都可能是一些钱也可能是一个钻石。
现在你知道如果打开第i 个盒子,有pi/100 的概率能获得Vi 的钱,有
1 –Pi/100 的概率能获得1个钻石。
现在你想知道,自己恰好获得k(0 <= k <=n) 个钻石,并且获得钱数大
于等于m 的概率是多少。
请你对0 <= k <= n 输出n+1 个答案。
答案四舍五⼊保留3 位⼩数。
输入输出格式
输入格式:
第⼀⾏两个整数n,m,见题意。
接下来n 行,每行两个整数Vi; Pi。
输出格式:
输出共n+1 行,表示0 <=k <= n 的答案。
输入输出样例
2 3 2 50 3 50
0.250 0.250 0.000
说明
对于30% 的数据, n <=10。
对于60% 的数据, n <=15
对于100% 的数据,n <= 30; 1 <= Pi <= 99; 1 <= Vi <= 10^7; 1 <=m <=10^7。
暴力搜索60
我们搜索从每一个盒子中取出钻石还是钱,分别算出其概率,然后我们在所有的盒子都打开以后判断当前这种情况获得的钱数是否大于等于m,如果是的话ans[s]更新,s为钻石数目,我们用一个ans数组统计获得几颗钻石的情况下的概率。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 50
using namespace std;
double ans[N];
int n,m,v[N],p[N];
int read()
{
,f=; char ch=getchar();
;ch=getchar();}
+ch-',ch=getchar();
return x*f;
}
void dfs(int now,int s,int c,double w)
{
)
{
if(c>=m) ans[s]+=w;
return ;
}
dfs(now+,s+,c,w*());
dfs(now+,s,c+v[now],w*p[now]*);
}
int main()
{
n=read(),m=read();
;i<=n;i++) v[i]=read(),p[i]=read();
dfs(,,,1.0);
;i<=n;i++)
printf("%.3lf\n",ans[i]);
;
}
60分搜索
正解为双向搜索,meet in the middle
我们通过前面的可以看到暴力搜索的话只能拿到60分,我们要想一个办法对这个搜索进行优化,我们可以先搜后一半,然后在前一半中找出与后一半合并以后能满足条件的状态,
满足的条件就是钱数>=n。对于每一种状态我们可以用
一个三元组表示{a,b,c}表示状态的钻石个数为a,钱数为b,概率为c。
对于这样一组样例
2 50
3 50
--------
4 50
5 50
那么前一半的状态用三元组表示为
{0,5,0.25},{1,3,0.25},{1,2,0.25},{1,3,0.25};
好,我们知道这样表示了。代码实现的主要过程就是,我们搜索后一半的状态,
找前一半有多少符合的。
例如,现在我们已经搜出后一半的所有三元组了。
前一半的某个状态为{cnt,money,nowp},那么我们至少需要的钱就是L=m-money,
那就需要找后一半状态里钱数大于等于L的,可以二分找。对于后一半的所有状态,按钻石数分块,
意思是,钻石数为0的放在一起,为1的放在一起...,并且对于每一块做概率的前缀和。找出每一块里
钱数大于等于L的那个状态,就可以用前缀和求出钱数大于等于L状态的概率的总和tmp。那么钻石
数为p时最答案的贡献就是,在后一半找到的概率和tmp,和前一半的现在搜到的状态的概率nowp的乘积。
(具体做法在代码中有注释)
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 50
using namespace std;
double p[N],ans[N];
int n,m,x,a,b,v[N];
vector<pair<int,double> >vec[N];
int read()
{
,f=; char ch=getchar();
;ch=getchar();}
+ch-',ch=getchar();
return x*f;
}
int main()
{
n=read(),m=read();
;i<=n;i++) v[i]=read(),x=read(),p[i]=x/.;
a=(n+)/;b=n-a;//由于我们要折半处理,因此我们现将其盒子分成两半
;i<=n;i++)
vec[i].clear();//可有可无、、
//对于每一种状态我们可以用个三元组表示{a,b,c}表示状态的钻石个数为a,钱数为b,概率为c
;st<<<b;st++)//我们先处理后一半盒子
{
;
,money=;//赋初值
;i<b;i++)//这个与前面构成一个大枚举,当前盒子为钻石还是钱
{
)//当前盒子中为钱
money+=v[n-i],np*=p[n-i];//钱的总数增加,概率相乘
else
s++,np*=(-p[n-i]);//钻石数+1
}
vec[s].push_back(make_pair(money,np));//我们将我们处理出来的所有情况储存在vec中
}
//我们处理了后一半的所有状态 ,将其存在vec数组中
//接下来的这个地方我们对我们处理出来的每一个数做一个分块处理,钻石数为0的放在一起,钻石数为1的放在一起,钻石数为2的放在一起、、、、并且对于每一块做概率的前缀和
;i<=n;i++)
{
sort(vec[i].begin(),vec[i].end());//我们将最小的可能不满足条件的放在前面,那么我们找出第一个满足条前的位置的时候,我们就可以知道在这个位置往前的一定都不满足条件
;j<vec[i].size();j++)
vec[i][j].second+=vec[i][j-].second;
}
//这个地方我们可以知道a*b+a*c+a*d=a*(b+c+d)而这个地方的(b+c+d)为后半段所有满足条件的概率总和,那么我们在这个地方就可以预处理一个前缀和
;st<<<a;st++)//我们再来根据搜出来的后半段的状态来找前半段的状态
{
;
,money=;
;i<a;i++)
{
)
money+=v[i+],np*=p[i+];
else
s++,np*=(-p[i+]);
}
//找能与搜出的前半段的状态合并起来以后能满足条件的后半段
//钻石数为s+i的这种状态可以由我们当前搜到的状态(存在了s颗钻石)我们可以再加上i颗钻石以后的钱数就可以满足条件,枚举这个可以使他满足条件的i
;i<=b;i++)//后一半一共有b个位置,总共就有b+1个状态,我们按照钻石的个数为一个状态
{
int l=m-money;//我们当前搜到的前半段的钱数已经是money了,那么我们还剩下m-money的钱数就可以满足条件
vector<pair<int,double> >::iterator it=lower_bound(vec[i].begin(),vec[i].end(),make_pair(l,1.0));//获得第一个满足条件的位置
//我们找出第一个满足条件的位置 用it来记录
//我们可以认为vec为一个数组
double tmp=vec[i].back().second;//现将tmp初始为整个数组的值
if(it!=vec[i].begin())//我们判断当期位置是否为数组的第一个位置,如果是的话就说明数组中的每一种状态都满足条件,总概率即为tmp
it--,tmp-=it->second; //如果不是的话,那么it为第一个满足条件的位置,it-1就是第一个不满足条件的位置,我们在减去it-1这一部分的前缀和,那么剩下的就是所有的满足条件的概率
ans[s+i]+=tmp*np;//搜到当前钻石数的概率为前半段的概率*后半段的概率
}
}
;i<=n;i++)
printf("%.3lf\n",ans[i]);
;
}
AC代码
10.1综合强化刷题 Day5的更多相关文章
- 10.1综合强化刷题 Day3 morning
竞赛时间:????年??月??日??:??-??:?? 题目名称 a b c 名称 a b c 输入 a.in b.in c.in 输出 a.out b.out c.out 每个测试点时限 1s 1s ...
- 10.1综合强化刷题 Day3 afternoon
竞赛时间:????年??月??日??:??-??:?? 题目名称 a b c 名称 a b c 输入 a.in b.in c.in 输出 a.out b.out c.out 每个测试点时限 1s 1s ...
- 10.1综合强化刷题 Day2 morning
一道图论神题(god) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK有一张无向图G={V,E},这张无向图有n个点m条边组成.并且这是一张带权图,只有 ...
- 10.1综合强化刷题 Day2 afternoon
最大值(max) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK有一本书,上面有很多有趣的OI问题.今天LYK看到了这么一道题目: 这里有一个长度为n的 ...
- 10.1综合强化刷题 Day7
noip提高组模拟赛 ...
- 10.1综合强化刷题 Day1 afternoon
一道图论好题(graph) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK有一张无向图G={V,E},这张无向图有n个点m条边组成.并且这是一张带权图, ...
- 10.1综合强化刷题 Day6
T1 排序 题目描述 小Z 有一个数字序列a1; a2; .... ; an,长度为n,小Z 只有一个操作:选 定p(1<p<n),然后把ap 从序列中拿出,然后再插⼊到序列中任意位置. ...
- 10.1综合强化刷题 Day4
财富(treasure) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK有n个小伙伴.每个小伙伴有一个身高hi. 这个游戏是这样的,LYK生活的环境是以 ...
- 10.1综合强化刷题 Day3
括号序列(bracket) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK有一个括号序列,但这个序列不一定合法. 一个合法的括号序列如下: ()是合法的 ...
随机推荐
- 6、python中的元组
元组(tuple)是python中有序.不可变的数据结构.元组还是python四种数据结构中唯一一种不可变的数据结构. 一.前言 元组在很多方面都变现得跟列表一样,除了列表储存得对象是可变得,而元组储 ...
- iview框架 两侧弹框 出现第二层弹框 一闪而过的问题
分析原因:寡人怀疑可能是,两层弹出框 采用的是一个开关值,发生了覆盖 解决方式 是在第二层弹框外套层计时器 源代码如下: 修改后为:
- hadoop ha集群搭建
集群配置: jdk1.8.0_161 hadoop-2.6.1 zookeeper-3.4.8 linux系统环境:Centos6.5 3台主机:master.slave01.slave02 Hado ...
- tomcat内存泄漏存入dump文件
很多tomcat进程退出(或者进程假死),都是由于频繁的抛出OutOfMemeoryError导致的. 为了让tomcat退出前或者发生OutOfMemeoryError时自动dump堆栈信息,方便事 ...
- IOS开发---菜鸟学习之路--(十二)-利用ASIHTTPRequest进行异步获取数据
想要实现异步获取的话我这边了解过来有两个非常简单的方式 一个是利用ASIHTTPRequest来实现异步获取数据 另一个则是利用MBProgressHUD来实现异步获取数据 本章就先来讲解如何利用AS ...
- xml文件的生成
关于android中自定义xml文件的生成,请看示例代码(主要来源于黑马教程): import java.io.File; import java.io.FileNotFoundException; ...
- copy & deepcopy
1 import copy 2 3 字典参照列表结论,看是否有深层嵌套. 4 a = {'name':1,'age':2} 5 b = a 6 a['name'] = 'ff' 7 print(a) ...
- 【转载】zookeeper使用和原理探究(一)
最近开始看到一些公司在使用zookeeper,本身对此了解的很少,这里看到一篇非常好的文章,因此转载 原贴地址:http://www.blogjava.net/BucketLi/archive/201 ...
- Struts2拦截器原理
拦截器是struts2处理的核心,本文主要说struts2的拦截器的基本原理/实现,其它框架处理的东西就不说了,得自己再看了.struts2版本:2.2.3当一个请求来了后,从org.apache.s ...
- eclipse中 tomcat首页server Locations变灰无法编辑
解决办法: 1.首先将Servers中部署的工程全部清空 2.然后对Tomcat v8.0 Server at localhost,点右键进行clean处理,再重新双击打开server服务即可.