2016-9-16NOIP模拟题

今天的模拟题果断滚粗了,10分。。。坐观zztAK虐场,orz

T1 防线

Smart学习数学竞赛的时候受尽了同仁们的鄙视,终于有一天……受尽屈辱的Smart黑化成为了黑暗英雄Lord Smart。就如同中二漫画的情节一样,Lord Smart打算毁掉这个世界。
数学竞赛界的精英Sarah打算阻止Lord Smart 的阴谋,于是她集合了一支由数学竞赛选手组成的超级行动队。由于队员们个个都智商超群,很快,行动队便来到了Lord Smart的黑暗城堡的下方。但是,同样强大的Lord Smart 在城堡周围布置了一条“不可越过”的坚固防线。防线由很多防具组成,这些防具分成了N 组。我们可以认为防线是一维的,那么每一组防具都分布在防线的某一段上,并且同一组防具是等距离排列的。也就是说,我们可以用三个整数S,E 和D 来描述一组防具,即这一组防具布置在防线的S,S + D,S + 2D,...,S + KD(K∈Z,S + KD≤E,S + (K + 1)D>E)位置上。黑化的 Lord Smart 设计的防线极其精良。如果防线的某个位置有偶数个防具,那么这个位置就是毫无破绽的(包括这个位置一个防具也没有的情况,因为0也是偶数)。只有有奇数个防具的位置有破绽,但是整条防线上也最多只有一个位置有奇数个防具。
作为行动队的队长,Sarah要找到防线的破绽以策划下一步的行动。但是,由于防具的数量太多,她实在是不能看出哪里有破绽。作为Sarah可以信任的学弟学妹们,你们要帮助她解决这个问题。

Input

第一行是一个整数T,表示有T 组互相独立的测试数据。
每组数据的第一行是一个整数 N。
之后 N 行,每行三个整数Si,Ei,Di,代表第i 组防具的三个参数。

Output

对于每组测试数据,如果防线没有破绽,即所有的位置都有偶数个防具,输出一行“There's no weakness.”(不包含引号)
否则在一行内输出两个空格分隔的整数 P 和C,表示在位置P 有C 个防具。当然C 应该是一个奇数。

Sample Input

3
2
1 10 1
2 10 1
2
1 10 1
1 10 1
4
1 10 1
4 4 1
1 5 1
6 10 1

Sample Output

1 1
There's no weakness.
4 3

Hint

30% 的数据:防具总数不多于10^7。
100% 的数据:防具总数不多于10^8,Si≤Ei,1≤T≤5,N≤200000,0≤Si,Ei,Di≤2^31-1。
Analysis:
1.用set乱搞(第一次在考场上用set,果然炸了。。。)期望的分:10分
2.枚举奇数个防具的位置,每次检查一下  期望的分:30分
3.二分奇数个防具的位置mid, 由于 整条防线上也最多只有一个位置有奇数个防具。”, 所以每次只要计算从最左端到mid的防具个数
时间复杂度:O(nlogn)
Introspection:
一拿到这题我一直在想找规律,压根就没往枚举奇数个防具的位置上去想。。。思路没打开,以后碰到可以nlogn的题就要往二分上去想
code:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<bits/stdc++.h>
using namespace std;
const int maxn=200050;
const int inf=1<<31-1;
int T,N;
long long maxx=0;
int S[maxn],E[maxn],D[maxn];
inline int read(){
int x=0;char ch=getchar();
while(ch<'0'||ch>'9'){ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x;
}
inline int check(int x){
int i,now,res=0;
for(i=1;i<=N;i++){
now=min(x,E[i]);
if(now>=S[i])res+=((now-S[i])/D[i]+1);
}
return res;
}
inline void Binary_Search(){
long long left=0,right=maxx,mid=(left+right)>>1,ans=inf;
while(left<=right){
mid=(left+right)>>1;
if(check(mid)&1){
right=mid-1;
if(mid<ans)ans=mid;
}
else left=mid+1;
}
if(ans!=inf)printf("%lld %d\n",ans,check(ans)-check(ans-1));
else printf("There's no weakness.\n");
}
int main(){
int i;T=read();
while(T--){
N=read();maxx=0;
for(i=1;i<=N;i++){
S[i]=read();E[i]=read();D[i]=read();
if(E[i]>maxx)maxx=E[i];
}
Binary_Search();
}
return 0;
}
T2:星象仪

Description

在寂寞的夜里,星象仪是非常浪漫的东西。但是,你作为一个精神稍微有点不太正常的Geek,把原本正常的星象仪改造得像电报发送器一样。当然,你这个的构造还要更加奇葩一点。具体来说,你的星象仪是一棵满二叉树,二叉树的节点都是有两个输入端和一个输出端的AND 门或者OR 门。它们输入和输出的信号都是只是0 或者1。它们会接受子节点的输出信号,然后将这两个信号进行AND 运算或者OR 运算作为自己的输出。然后,根节点的输出信号就是整个星象仪的输出信号。叶节点的输入信号是由你来调整的,如果二叉树有K 层,那么你显然有2K个输入信号可以调整。调整一次当然只能改变一个输入信号。根据你的设定,在一开始所有的输入端的输入信号都是0。现在你希望用星象仪得到一串信号,为此,你需要不停地调整输入。

假定你想要用上图中的星象仪得到输出信号000111,一种可行的方案是0001→0011→1100→1111→1010→0101,但是这样你要调整14 次输入信号。更加方便的方式是0000→0000→0000→0101→0101→0101,这样你总计只需要调整2次输入信号。
由于调整输入信号是一件非常麻烦的事情,现在你希望知道对于一台给定的星象仪,如果想要得到一串给定的信号,至少需要调整多少次输入。

Input

输入包含多组测试数据。第一行有一个整数T,表示测试数据的组数。
每组测试数据的第一行是一个正整数 N,表示输入信号的数目。保证N 是2 的整数次幂。
第二行含有一个由 0 和1 组成的字符串S,表示你想要得到的信号。
第三行包含 N – 1 个整数,按照层次遍历顺序给出满二叉树的每个节点。整数只会是0或者1。0 表示二叉树的这个位置是一个OR 门,1 表示是一个AND 门。

Output

对于每组测试数据,在单独的一行内输出结果。

Sample Input

2
4
010101
0 0 0
4
111111
1 1 1

Sample Output

5
4

Hint

30% 的数据:N≤16,S的长度在100 之内。
100% 的数据:T≤100,N≤8192,S的长度在10000 之内。
Analysis:
可以算出每个顶点变成1所需的最小花费,用f[i]来表示
1.若i为OR,f[i]=max{f[i*2],f[i*2+1]}
2.若i为AND,f[i]=f[i*2]+f[i*2+1]}
可以在S前加上一个0,之后在第一个1时需加上f[1],后面每一次变动只需加1
Introspection:
看到题目时没有仔细分析题目的本质,应该想到这个DP,以后应注意
code:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<bits/stdc++.h>
using namespace std;
const int maxn=10005;
int T,N;
char s[maxn];
int num[maxn];
int f[maxn*2];
inline int read(){
int x=0;char ch=getchar();
while(ch<'0'||ch>'9'){ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x;
}
inline void init(){
int i;
for(i=N*2-1;i>=N;i--)f[i]=1;
for(;i>=1;i--){
if(num[i])f[i]=f[i*2]+f[i*2+1];
else f[i]=min(f[i*2],f[i*2+1]);
}
}
inline void work(){
int len=strlen(s+1),i=1;
int ans=0;
while(s[i]==s[i-1]&&i<=len)i++;
ans+=f[1];
for(i++;i<=len;i++)
if(s[i]!=s[i-1])ans++;
printf("%d\n",ans);
}
int main(){
int i;T=read();
while(T--){
N=read();
scanf("%s",s+1);s[0]='0';
for(i=1;i<N;i++)scanf("%d",&num[i]);
init();
work();
}
return 0;
}
T3:分形之城

Description

城市的规划在城市建设中是个大问题。不幸的是,很多城市在开始建设的时候并没有很好的规划,城市规模扩大之后规划不合理的问题就开始显现。而这座名为Fractal 的城市设想了这样的一个规划方案,如下图所示:

当城区规模扩大之后,Fractal 的解决方案是把和原来城区结构一样的区域按照图中的方式建设在城市周围,提升城市的等级。对于任意等级的城市,我们把正方形街区从左上角开始按照道路标号。虽然这个方案很烂,Fractal 规划部门的人员还是想知道,如果城市发展到了等级N,编号为A 和B 的两个街区的直线距离是多少。街区的距离指的是街区的中心点之间的距离,每个街区都是边长为10 米的正方形。

Input

输入包含多组测试数据,第一行有一个整数T 表示测试数据的数目。
每组测试数据包含一行三个整数 N, A, B,表示城市等级以及两个街区的编号。

Output

对于每组测试数据,在单独的一行内输出答案,四舍五入到整数。

Sample Input

3
1 1 2
2 16 1
3 4 33

Sample Output

10
30
50

Hint

30% 的数据:N≤5,T≤10。
100% 的数据:N≤31,1≤A,B≤2^2N,T≤1000。
Analysis:
1.打表 期望的分:30分(然而我表都打错了
2.递归求解 把整个图分成四块,每块的等级比原图-1,对于每一块有不同的情况,需要分类讨论 期望的分:100分
code:等我A了在发吧。。。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值