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[n]); 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[n];i<=100;i++){ ans=min(ans,f[i]); } printf("%d\n",ans); return 0; }