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;
}