您的位置:首页 > 其它

[1031-1101]模拟赛

2011-11-03 17:40 239 查看
Day1

题目名称(中文)

买彩票

数学题

终极大水题

题目名称(英文)

Maicaipiao

Shuxueti

zhongjidashuiti

输入格式

Ticket.in

Math.in

Super.in

输出格式

Ticket.out

Math.out

Super.out

买彩票(水题第一道) 电视里面正放着“抽百万大奖,赢幸福生活”的宣传广告,小yjw看后也想去试试手气,当然,作为hzoi的高材生,他可不屑只是单纯的去碰运气。经过他的一番分析,发现,商家在彩票里面做了手脚,使得每个抽奖点的中奖概率不是完全一样的,而且随着时间的变化而变化,不过这种变化是有规律的。对于第I个抽奖点,最开始的中奖概率是百万分之Pi,以后每抽一张彩票后都要重新排队,花费的时间是T分钟,每抽一次减少的概率为Di。 由于可怜的小Yjw还有一大堆的知识没有复习,他只能抽出H个小时去买彩票。由于抽奖地点都在一路公共汽车的线路上,所以怕麻烦的小Yjw决定按车站顺序抽奖,当然,小Yjw可以从任意一站开始抽奖,对于经过的抽奖点可以买彩票,也可以不买。假设从第I个抽奖点到第I+1个抽奖点需要做Ci分钟的汽车。 小yjw希望能在有限的H个小时内获得最好的运气——即抽奖的概率和最大。 [输入] 输入文件名:(tickt.in) 第一行为一个整数n,表示抽奖点的个数,1<=n<=200 第二行是两个整数H和T,1<=H<=10,1<=T<=60。 接下来的n行,每行3个整数,分别是Pi,Di,Ci(Cn=0)。1<=Pi<=10000,Di<=Pi,1<=Ci<=600。 [输出] 输出文件名:(tickt.out) 文件仅有一行,为一个整数,即抽奖概率和的最大值。 【输入输出样例】
tickt.in

tickt.out

2 1 20 200 100 10 300 200 0

500

【样例说明】 首先,小Y从1号开始抽奖,花费20分钟,得到概率200,然后坐车到2号,花费10分钟,再花20分钟得到概率300,概率和是500,花费50分钟。

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
int p[210],d[210],c[210],tmp[210];
int H,T,n;
int ans,sum;
void calc(int s,int t){
int Time=0,id;
for (int i=s;i<t;i++) Time+=c[i];
if (Time>H) return;
Time=(H-Time)/ T;
memcpy(tmp,p,sizeof(p));
for (;Time>0;Time--){
int max=0;
for (int i=s;i<=t;i++){
if (tmp[i]>max){
max=tmp[i];
id=i;
}
}
if (max==0) break;
tmp[id]-=d[id];
sum+=max;
}
}
int main(){
freopen("ticket.in","r",stdin);
freopen("ticket.out","w",stdout);
scanf("%d%d%d",&n,&H,&T);
for (int i=1;i<=n;i++) scanf("%d%d%d",&p[i],&d[i],&c[i]);
H*=60;
for (int i=1;i<=n;i++){
for (int j=i;j<=n;j++){
sum=0;
calc(i,j);
if (sum>ans) ans=sum;
}
}
printf("%d\n",ans);
return 0;
}

水水的数学题(math)
话说zsz理科学的非常的棒啊,尤其是那个物理,暴虐全场,那曾经高出班级平均分30分的成绩让别人看了不免眼红。虽然其他的女生嘴上不说,可是zsz清清楚楚地看在了眼里,他赤裸裸的被很多女生暗恋了。可是,zsz是什么人?纯洁的小少男(我怎么不知道?),所以自从那次太过于招摇以后,zsz就下定决心从此以后再也不亲手做一道和理科有关的题了。今天,zsz就遇到了一道大水题(可是在他的眼里又有什么题不水呢?),貌似只
有加减吧,你只需要按照下面的规则解出来就行了
1.zsz会给出一个数n,表示你需要对1~n这n个数进行一定的处理,使其结果为0。
2.例如1 - 2 . 3 - 4 . 5 + 6 . 7 表示1-23-45+67 其结果显然是0吧。
3.保证运算符号只有+,-,.三种,具体含义看上面的式子,你懂得。
4.对于给定的每个n,你只需要输出其前20组可能的情况,不足20种就有几种输出几种。
5.最后一行,输出总的解的个数
输入样例
7
输出样例
1 + 2 - 3 + 4 - 5 - 6 + 7
1 + 2 - 3 - 4 + 5 + 6 - 7
1 - 2 + 3 + 4 - 5 + 6 - 7
1 - 2 - 3 - 4 - 5 + 6 + 7
1 - 2 . 3 + 4 + 5 + 6 + 7
1 - 2 . 3 - 4 . 5 + 6 . 7
6
样例解释:具体每种运算符号的优先级自己由样例推导,+高于-,-高于.(不懂得只能说明你智商低于50%)。
N<=15,具体算法,你懂得。
特别提示:输出格式中在数字和运算符之间是有空格滴`````

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
int n;
int d[20];
int ans[16]={0,0,0,1,1,1,1,6,10,11,17,88,162,197,437,1350};
int sum;
bool calc(){
int tot=0;
int last=1;
int flag=1;
for (int i=0;i<n-1;i++){
if (d[i]==1){
tot+=(flag==1)?last:-last;
last=i+2;
flag=1;
}else if (d[i]==2){
tot+=(flag==1)?last:-last;
last=i+2;
flag=2;
}else if (d[i]==3){
int t=10;
if (i+1>=9) t*=10;
last=last*t+i+2;
}
}
tot+=(flag==1)?last:-last;
return (tot==0)?1:0;
}
void dfs(int step){
if (step>=n-1){
if (calc()){
++sum;
if (sum<=20){
printf("1");
for (int i=0;i<n-1;i++){
if (d[i]==1) printf(" + %d",i+2);
else if (d[i]==2) printf(" - %d",i+2);
else if (d[i]==3) printf(" . %d",i+2);
}
putchar('\n');
}
}
return;
}
for (int i=1;i<=3;i++){
d[step]=i;
dfs(step+1);
if (sum>=20) return;
}
}
int main(){
freopen("math.in","r",stdin);
freopen("math.out","w",stdout);
scanf("%d",&n);
dfs(0);
printf("%d\n",ans
);
return 0;
}

终极大水题(super)
对于任何正整数x,其约数的个数记作g(x)。例如g(1)=1、g(6)=4。
如果某个正整数x满足:g(x)>g(i) 0<i<x,则称x为反质数。例如,整数1,2,4,6等都是反质数。
现在给定一个数N,你能求出不超过N的最大的反质数么
输入只有一行,一个数N(1<=N<=2,000,000,000)。
输出也只有一行,为不超过N的最大的反质数。

【输入输出样例】
super.in

super.out

1000

840

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int Min,Max,n;
int prime[10]={0,2,3,5,7,11,13,17,19,23};
void dfs(int step,int k,int m,int j){
if (step>9 || m==0){
if (k==Max){
if (j<Min) Min=j;
}else if (k>Max){
Max=k;
Min=j;
}
return;
}
int i=0;
for(;;){
dfs(step+1,k*(i+1),i,j);
if (j<=(n/prime[step])) j=j*prime[step];
else return;
++i;
if (i>m) return;
}
}
int main(){
freopen("super.in","r",stdin);
freopen("super.out","w",stdout);
scanf("%d",&n);
dfs(1,1,100,1);
printf("%d\n",Min);
return 0;
}


Day2

水题模拟赛加强版

题目名称

分卷子

Interval

telewire

可执行文件名

Paper

Interval

telewire

输入文件

Paper.in

Interval.in

telewire.in

输出文件

Paper.out

Interval.out

telewire.out

分卷子
As is kown, yjw是伟大的410的物理课代表。但是作为物理课代表却常常要面临分卷子的任务,任务来了:
Yjw需要N堆特定张数的卷子。摆在他面前的是一整摞卷子,这摞卷子的总张数恰好为所需要的卷子数的和。你需要把这摞卷子分成上述所需的N份。分卷子是需要耗费力气的,我们规定分X张卷子,耗费X个单位的力气。Yjw想让他分卷子所耗费的力气最小,请你来帮帮他吧。
输入格式:第一行一个整数N表示yjw所需卷子的堆数
接下来的N行,每行一个整数,表示所需的每堆卷子的张数。
输出格式:一个整数,表示对卷子分了N-1次后,yjw耗费的最小力气。
输入样例:
3
8
5
8
输出样例:
34
样例解释:
起初卷子的张数为21,第一次分卷子后,耗费的力气为21,把卷子分为13和8的两堆,然后花费13个单位的力气将张数为13的那堆卷子分成张数为8和5的两堆,这样的耗费的总力气为34;

#include <cstdio>
#include <cstring>
int n;
long long hp[1000000];
int tot;
long long ans;
void swap(long long &a,long long &b){long long c=a;a=b;b=c;}
void up(int n){
int i=n;
while ((i >> 1)>0 && hp[i >> 1]>hp[i]){
swap(hp[i >> 1],hp[i]);
i >>= 1;
}
}
void down(int n){
int i=1;
while ((i << 1)<=n){
i <<= 1;
if (i<n && hp[i+1]<hp[i]) i++;
if (hp[i >> 1]>hp[i]) swap(hp[i >> 1],hp[i]);else break;
}
}
int main(){
freopen("paper.in","r",stdin);
freopen("paper.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;i++){
long long x;
scanf("%I64d",&x);
hp[++tot]=x;
if (tot>1) up(tot);
}
while (tot>1){
long long x=hp[1];
swap(hp[tot],hp[1]);
tot--;
down(tot);
long long y=hp[1];
swap(hp[tot],hp[1]);
tot--;
down(tot);
ans+=x+y;
hp[++tot]=x+y;
if (tot>1) up(tot);
}
printf("%I64d\n",ans);
return 0;
}


interval
题目描述:给你n个整点区间,这n个整点区间是一个大整点区间的子区间。对于整点区间[a,b],是这样定义的:区间[a,b]饱含且仅饱含大于等于a,且小于等于b的所有整数,那么称区间[a,b]为整点区间。我们将整点区间[a,b]中的整数抽象为若干个点,我们在这些点上可以放一个元素或者不放元素,再对[a,b]加以限制,比如整点区间[a,b]至少有c个点上放有元素。我们的任务就是求出对于给定的n个整点区间都满足上述限制的情况下,所需的最少元素个数。
输入格式:
第一行一个整数n
第二行到第n+1行,每行三个用空格隔开的整数a,b,c;意义如题目所述。
输出格式:
一行一个整数表示最少的元素个数
输入样例:
5
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1
输出样例:
6
数据范围:
0<=N<=50000
0<=A,b<=50000
0<C<=b-a+1

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
using namespace std;
struct node{
int x,w,next;
}e[500000];
int k[51000];
bool v[51000];
int d[51000];
int tot;
int n,m;
int max(int a,int b){return a>b?a:b;}
void add(int a,int b,int c){
e[++tot].x=b;
e[tot].w=c;
e[tot].next=k[a];
k[a]=tot;
}
int f[1000000];
void SPFA(){
int head=0,tail=1;
memset(d,200,sizeof(d));
memset(v,0,sizeof(v));
d[0]=0;
v[0]=true;
f[1]=0;
while (head<tail){
int x=f[++head];
v[x]=false;
for (int t=k[x];t!=-1;t=e[t].next){
if (d[e[t].x]<d[x]+e[t].w){
d[e[t].x]=d[x]+e[t].w;
if (!v[e[t].x]){
v[e[t].x]=true;
f[++tail]=e[t].x;
}
}
}
}
}
int main(){
freopen("interval.in","r",stdin);
freopen("interval.out","w",stdout);
scanf("%d",&n);
memset(k,-1,sizeof(k));
for (int i=1;i<=n;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(a-1,b,c);
m=max(m,b);
}
for (int i=1;i<=m;i++){
add(i,i-1,-1);
add(i-1,i,0);
}
SPFA();
printf("%d\n",d[m]);
return 0;
}

Telewire
最近,约翰的奶牛们越来越不满足于牛棚里一塌糊涂的电话服务,于是,她们
要求约翰把那些老旧的电话线换成性能更好的新电话线。新的电话线架设在已有的n根电话线杆上,第i根电话线的高度为hi,(1=<hi<=100)。电话线总是从一根电话线杆的顶端被引到相邻的那根的顶端,如果这两根电话线杆的高度hi和hj不同,那么约翰就必须支付c*abs(hi-hj)的费用,当然,你不能移动电话线杆,只能按照原有的顺序在相邻杆间架设电话线。
加高某些电话线杆能减少架设电话线的总费用,尽管这项工作也需要支付一定的费用。更准确的说,如果他把一根电话线杆加高x米的话,他需要付出x^2费用。
请你帮约翰计算一下,如果合理的进行这两项工作,他最少要在这个电话线改造工程中花多少钱。
输入说明
第一行输入两个数n和c,含义如上
接下来n行,每行一个整数hi
输出说明
输出约翰完成电话线改造工程需要花费的最小费用
输入样例
5 2
2
3
5
1
4
输出样例
15
数据范围
N<=100000
C<=100;
Hi<=100;

#include <cstdio>
#include <cstring>
int n,c;
int f[105];
int low[105],high[105];
int a[100005];
inline int sqr(int x){return x*x;}
inline int min(int a,int b){return a<b?a:b;}
int main(){
freopen("telewire.in","r",stdin);
freopen("telewire.out","w",stdout);
scanf("%d%d",&n,&c);
for (int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
memset(f,63,sizeof(f));
for (int i=a[1];i<=100;i++) f[i]=sqr(i-a[1]);
low[0]=high[101]=0x7fffffff;
for (int i=1;i<=100;i++){
low[i]=min(low[i-1],f[i]-i*c);
}
for (int i=100;i>0;i--){
high[i]=min(high[i+1],f[i]+i*c);
}
for (int i=2;i<=n;i++){
memset(f,63,sizeof(f));
for (int j=a[i];j<=100;j++){
f[j]=min(low[j]+j*c,high[j]-j*c)+sqr(j-a[i]);
}
for (int j=1;j<=100;j++){
low[j]=min(low[j-1],f[j]-j*c);
}
for (int j=100;j>0;j--){
high[j]=min(high[j+1],f[j]+j*c);
}
}
int ans=0x7fffffff;
for (int i=a
;i<=100;i++){
ans=min(ans,f[i]);
}
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: