小奇模拟赛9.13 by hzwer
2015年9月13日NOIP模拟赛
by hzwer (这是小奇=>
小奇挖矿(explo)
【题目背景】
小奇要开采一些矿物,它驾驶着一台带有钻头(初始能力值w)的飞船,按既定路线依次飞过喵星系的n个星球。
【问题描述】
星球分为2类:资源型和维修型。
1.资源型:含矿物质量a[i],若选择开采,则得到a[i]*p的金钱,之后钻头损耗k%,即p=p*(1-0.01k)
2.维修型:维护费用b[i],若选择维修,则支付b[i]*p的金钱,之后钻头修复c%,即p=p*(1+0.01c)
(p为钻头当前能力值)
注:维修后钻头的能力值可以超过初始值
请你帮它决策最大化这个收入
【输入格式】
第一行4个整数n,k,c,w。
以下n行,每行2个整数type,x。
type为1则代表其为资源型星球,x为其矿物质含量a[i];
type为2则代表其为维修型星球,x为其维护费用b[i];
【输出格式】
输出一行一个实数(保留两位小数),表示要求的结果。
【样例输入】
5 50 50 10
1 10
1 20
2 10
2 20
1 30
【样例输出】
375.00
【数据范围】
对于30%的数据 n<=100
对于50%的数据 n<=1000,k=100
对于100%的数据 n<=100000,0<=k,c,w,a[i],b[i]<=100
保证答案不超过10^9
贪心
对于飞船 当前决策只对后续有影响 ->倒着贪心就没有后效性了
而剩余耐久度与之后的开采收益成正比
①如果是资源型 就选挖或者不挖
②如果是维修型 就选修或者不修
//更新ans ans是 是倒着得到的钱数表示以前至少弄到多少
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 100005 using namespace std; float n,k,c,m; int a[maxn],b[maxn]; double ans=0; int main() { cin>>n>>k>>c>>m; k=1-0.01*k;c=1+0.01*c; for(int i=1;i<=n;++i) { scanf("%d%d",&a[i],&b[i]); } for(int i=n;i;--i) { if(a[i]==1)ans=max(ans,ans*k+b[i]); else ans=max(ans,ans*c-b[i]); } printf("%.2lf",ans*w); return 0; }
小奇的数列(seq)
【题目背景】
小奇总是在数学课上思考奇怪的问题。
【问题描述】
给定一个长度为n的数列,以及m次询问,每次给出三个数l,r和P,询问 (a[l'] + a[l'+1] + ... + a[r']) mod P的最小值。
其中l <= l' <= r' <= r。
即模意义下的区间子串和最小值。
【输入格式】
第一行包含两个正整数n和m,表示数列的长度和询问的个数。
第二行为n个整数,为a[1]..a[n]。
接下来m行,每行三个数l,r和P,代表一次询问。
【输出格式】
对于每次询问,输出一行一个整数表示要求的结果
【样例输入】
4 2
8 15 9 9
1 3 10
1 4 17
【样例输出】
2
1
【数据范围】
对于20%的数据 n<=100,m<=100,p<=200
对于40%的数据 n<=200,m<=1000,p<=500
对于70%的数据 n<=100000,m<=10000,p<=200
对于100%的数据 n<=500000,m<=10000,p<=500,1<=a[i]<=10^9
AC需使用平衡树来寻找最小差值,复杂度为m*p*logp,需要手写treap,splay或替罪羊树等
//set由于常数较大也不资磁
//大于NOIP难度
//详情访问http://hzwer.com/7613.html
对于20%的数据:暴力在区间内枚举子串求和取模,最后得出最小值
优化:
①根据抽屉原理(现在把r-l+1个数字塞入p个箱子,如果r-l+1>p那肯定有个箱子里面的数超过两个,那相同箱子里面的数字相同) 特判输出0
②根据生日悖论(生日悖论:指如果一个房间里有23个或23个以上的人,那么至少有两个人的生日相同的概率要大于50%。这就意味着在一个典型的标准小学班级(30人)中,存在两人生日相同的可能性更高。对于60或者更多的人,这种概率要大于99%),考虑数据随机生成,如果找到两个前缀和相等的直接返回0
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 100005 using namespace std; int n,m; int a[maxn]; long long sum[maxn]; long long ans; void query(int l,int r,int p) { if(l-r>=p) { puts("0"); return; } else ans=p; for(int i=l-1;i<=r;++i) { for(int j=i+1;j<=r;++j) { if(sum[i]==sum[j]) { ans=0; break; } ans=min(ans,(sum[j]-sum[i])%p); } } printf("%lld",ans); puts(""); } int main() { cin>>n>>m; for(int i=1;i<=n;++i) { scanf("%d",&a[i]); sum[i]=sum[i-1]+a[i]; } int l,r,p; for(int i=1;i<=m;++i) { scanf("%d%d%d",&l,&r,&p); query(l,r,p); } return 0; }
小奇回地球(earth)
【题目背景】
开学了,小奇在回地球的路上,遇到了一个棘手的问题。
【问题描述】
简单来说,它要从标号为1的星球到标号为n的星球,某一些星球之间有航线。由于超时空隧道的存在,从一个星球到另一个星球时间可能会倒流,而且,从星球a到b耗费的时间和星球b到a耗费的时间不一定相同。
宇宙法规定:“禁止在出发时间前到达目的地。”
每艘飞船上都有速度调节装置,可以调节飞行的时间。其功能可以使得整次航程中所有两星球间的飞行时间增加或减少相同的整数值。你的任务是帮助它调整速度调节器,找出一条最短时间到达目的地的路径。
【输入格式】
输入文件包含多组数据,第1个数为T,表示数据组数。
对于每组数据,输入第1行为两个正整数n,m,为星球的个数和星球间的路线数。接下来m行,每行三个整数i,j和t,表示由星球i到星球j飞行的时间为t。由i到j最多只会有一条飞行线路。
【输出格式】
输出文件共T行,每组数据输出一行。
如果可以通过调节速度调节器完成任务,则输出一个非负整数,表示由星球1到星球n的最短时间。(注意最短时间要大于或者等于0)。
如果不能由星球1到达星球n,则输出-1。
【样例输入】
1
4 5
1 2 1
1 3 1
2 3 -3
3 1 1
3 4 1
【样例输出】
2
【样例解释】
把速度控制器的值设为1,相当于每个时间值加1,得到的最短路径为1→2→3→4,所需时间为2+(-2)+2=2。
【数据范围】
1,2号测试点,保证所有星球出度不超过1
3,4号测试点,n<=10
5,6号测试点,-100<=t<=100
对于100%的数据T<=10,n<=100,m<=n*(n-1),-100000<=t<=100000
数据随机和构造结合生成