9.18 test solution.

来源:互联网 发布:公司数据保密协议范本 编辑:程序博客网 时间:2024/06/14 08:36

1.完美的序列(sequence.cpp/c/pas)

时空限制

时间限制:

1s

空间限制:

64MB

题目描述

LYK认为一个完美的序列要满足这样的条件:对于任意两个位置上的数都不相同。然而并不是所有的序列都满足这样的条件。

于是LYK想将序列上的每一个元素都增加一些数字(当然也可以选择不增加),使得整个序列变成美妙的序列。

具体地,LYK可以花费 1 点代价将第 i 个位置上的数增加 1 ,现在LYK想花费最小的代价使得将这个序列变成完美的序列。

输入输出格式

输入格式:

第一行一个数 n,表示数字个数。

接下来一行n个数ai,表示LYK得到的序列。

输出格式:

一个数表示变成完美的序列的最小代价。

输入输出样例

输入样例:

41 1 3 2

输出样例:

3

说明

对于30%的数据n5

对于60%的数据n1000

对于80%的数据n30000ai3000

对于100%的数据n1000001ai100000


solution

  • 要代价尽可能小,可以贪心的去解决

  • 开一个 exist 数组用来判断一个数是否在原序列中

  • a 数组记录原序列中重复的数

  • 先把 a 从小到大排序,然后贪心的修改

  • 对于当前的a[i] 肯定是要找不在原序列中并且大于 a[i] 的最小的数。

code

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;typedef long long ll;#define MAXN 100010template<typename T>inline void input(T &x) {    x=0; T a=1;    register char c=getchar();    for(;c<'0'||c>'9';c=getchar())        if(c=='-') a=-1;    for(;c>='0'&&c<='9';c=getchar())        x=x*10+c-'0';    x*=a;    return;}int a[MAXN],cntA;bool exist[MAXN<<1];//exist数组开两倍大小是为了防止下面RE//最坏的情况是100000个100000,那样最大会到199999,开两倍就好了。int main() {    int n;    input(n);    for(int i=1,x;i<=n;i++) {        input(x);        if(exist[x]) {            a[++cntA]=x;            continue;        }        exist[x]=true;    }    if(cntA==0) {        printf("0");        return 0;    }    sort(a+1,a+cntA+1);    int ans=0,nowA=1;    for(int i=1;nowA<=cntA;i++) {        if(i<a[nowA]||exist[i]) continue;        ans+=i-a[nowA++];    }    printf("%d",ans);    return 0;}

2.LYK与实验室(lab.cpp/c/pas)

时空限制

时间限制:

5s

空间限制:

64MB

题目描述

LYK在一幢大楼里,这幢大楼共有 n 层,LYK初始时在第 a 层上。

这幢大楼有一个秘密实验室,在第 b 层,这个实验室非常特别,对LYK具有约束作用,即若LYK当前处于 x 层,当它下一步想到达 y 层时,必须满足 |xy|<|xb|,而且由于实验室是不对外开放的,电梯无法停留在第b层。 LYK想做一次旅行,即它想按 k 次电梯,它想知道不同的旅行方案个数有多少个。

两个旅行方案不同当前仅当存在某一次按下电梯后停留的楼层不同。

输入输出格式

输入格式:

一行 4 个数,n,a,b,k

输出格式:

一个数表示答案,由于答案较大,将答案对1000000007取模后输出。

输入输出样例

输入样例#1:

5 2 4 1

输出样例#1:

2

输入样例#2:

5 2 4 2

输出样例#2:

2

输入样例#3:

5 3 4 1

输出样例#3:

0

说明

对于20%的数据n,k5

对于40%的数据n,k10

对于60%的数据n,k500

对于90%的数据n,k2000

对于100%的数据n,k5000


solution

  • f[i][j]表示第 i 次按停在第 j 层的方案数。

  • sum[i][j]=k=1jf[i][k],也就是f[i][j]的前缀和

  • 首先明白一点,能到达楼层 j 的楼层肯定是一段区间

  • 这个区间怎么算呢。看上面的式子。

  • |xj|<|xb|=(xj)2<(xb)2

  • 化简得到:x(2b2j)<b2j2

  • 分类讨论一下:

  • b>j(2b2j)>0

  • 所以原式 =x<b2j22b2j=x<b+j2

  • 同理也可推出来当b<j时,x>b+j2

  • 因为x是个整数,所以上面那两个式子可以在化简一下即:

  • b>j 时,xb+j2,其中表示向下取整。

  • b<j 时,xb+j2, 其中表示向上取整。

  • 这只是区间的一个边界,另一个怎么办?

  • b>j 时,另一个取1,因为可能不能从1j,但是那样sum[i][1]的值就会是0,不会对sum[i][x]的值有影响。

  • 同理,当 b<j 的时候,另一个直接取 n

  • 所以就可以列出下面的dp方程:

  • f[i][j]=sum[i1][r]sum[i1][l1]f[i1][j]

  • 其中

    l={1b+j2b>jb<j
    ,
    r={b+j2nb>jb<j

  • 所以dp方程可以写成这样

  • f[i][j]=sum[i1][b+j2]f[i1][j]sum[i1][n]sum[i1][b+j21]f[i1][j]b>jb<j

  • 最后ans=i=1nf[k][i] ,当然还要mod

  • 然而这样写出来怕是会MLE,所以把 fsum 变成滚动数组。

code

#include<cmath>#include<queue>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;typedef long long ll;#define MAXN 5010#define mod 1000000007template<typename T>inline void input(T &x) {    x=0; T a=1;    register char c=getchar();    for(;c<'0'||c>'9';c=getchar())        if(c=='-') a=-1;    for(;c>='0'&&c<='9';c=getchar())        x=x*10+c-'0';    x*=a;    return;}int f[2][MAXN];int sum[2][MAXN]; int main() {    int n,a,b,k;    input(n),input(a),input(b),input(k);    f[0][a]=1;    for(int i=a;i<=n;i++)        sum[0][i]=1;    for(int i=1;i<=k;i++) {        int now=i%2,last=(i+1)%2;        for(int j=1;j<=n;j++) {            int &dp=f[now][j];            if(j>b) {                int l=ceil((j+b+1)*0.5),r=n;//l这么算是因为浮点误差,不这么写会WA一两个点                dp=(sum[last][r]-sum[last][l-1]-f[last][j])%mod;            } else if(j<b) {                int r=floor((j+b-1)*0.5);                dp=(sum[last][r]-f[last][j])%mod;            }            if(dp<0) dp=(dp+mod)%mod;//因为是减法取模,注意变成负数            sum[now][j]=(sum[now][j-1]+dp)%mod;        }    }    int ans=0;    int end=k%2;    for(int i=1;i<=n;i++)        ans=(ans+f[end][i])%mod;    printf("%d",ans%mod);    return 0;}

3.旅行(travel.cpp/c/pas)

时空限制

时间限制:

1s

空间限制:

64MB

题目描述

LYK想去一个国家旅行。这个国家共有 n 个城市,有些城市之间存在道路,我们假定这些道路长度都是 1 的,更准确的说,共有 m 条道路。

我们定义城市A与城市B的最短路为AB的所有路径中,经过的道路最少的那条道路。最短路的长度为这条道路的所有道路长度之和,由于所有道路长度都为 1,因此假如AB之间最短路的道路条数为 k,则AB的最短路长度为 k

我们定义整个国家的最短路为任意两个城市(A,BB,A算作不同的点对)之间的最短路长度的和。

然而这个国家正处于危乱之中,极有可能一条道路会被恐怖分子炸毁。

LYK想知道,万一某条道路被炸毁了,整个国家的最短路为多少。若炸毁这条道路后整个国家不连通了,那么就输出“INF”(不加引号)。

输入输出格式

输入格式:

第一行两个数n,m

接下来 m 行,每行两个数u,v,表示存在一条道路连接u,v(数据保证不存在自环)。

输出格式:

输出m行,第 i 行的值表示当第 i 条道路被炸毁时,整个国家的最短路是多少,若图不连通,则输出“INF”。

输入输出样例

输入样例:

2 21 21 2

输出样例:

22

说明

对于20%的数据n10,nm100

对于40%的数据1n<m100

对于70%的数据1n100,n<m3000

对于再另外10%的数据对于所有节点i(1i<n),存在一条边连接 ii+1,且n=mn100

对于再另外10%的数据对于所有节点i(1i<n),存在一条边连接 ii+1,且n=mn1000

对于再另外10%的数据对于所有节点i(1i<n),存在一条边连接 ii+1,且n=mn100000


solution

  • no solution.

code

  • no code

我会补上的

原创粉丝点击