9.17模拟赛

T1 巧克力棒

题目描述

LYK 找到了一根巧克力棒,但是这根巧克力棒太长了,LYK 无法一口吞进去。

具体地,这根巧克力棒长为nn,它想将这根巧克力棒折成nn段长为11的巧克力棒,然后慢慢享用。

它打算每次将一根长为kk的巧克力棒折成两段长为aa和bb的巧克力棒,此时若a=ba=b,则LYK 觉得它完成了一件非常困难的事,并会得到11点成就感。

LYK 想知道一根长度为nn的巧克力棒能使它得到最多几点成就感。

输入输出格式

输入格式:

第一行一个数nn。


输出格式:

一个数表示答案。

输入输出样例

输入样例#1:

7

输出样例#1:

4

说明

对于20\%20%的数据,n \leq 5n≤5。

对于50\%50%的数据,n \leq 20n≤20。

对于80\%80%的数据,n \leq 2000n≤2000。

对于100\%100%的数据,n \leq 1000000000n≤1000000000。

样例解释

将77掰成3+43+4, 将33掰成1+21+2, 将44掰成2+22+2获得11点成就感, 将剩下的所有22掰成 1+11+1

获得33点成就感。总共44点成就感。

题解:

考试80分dp,计算局部最优值 枚举断点取最大

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,f[2017];
int main(){
    freopen("chocolate.in","r",stdin);
    freopen("chocolate.out","w",stdout);
    scanf("%d",&n);
    f[1]=0;f[2]=1;f[3]=1;
    for(int i=4;i<=n;i++){
        for(int j=0;j<=i;j++){
            f[i]=max(f[i],f[j]+f[i-j]);
        }
        if(i%2==0)f[i]=max(f[i],f[i/2]*2+1);
    }
    printf("%d\n",f[n]);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

正解:贪心

发现最后肯定分成n个长度为1,要求有贡献,那么长度为1的一定是由长度为2的分来的,分成长度为2 想要有贡献 必须从长度为4分来的,分成

长度为4想要有贡献 必须分成长度为8的.....所以将巧克力棒分成2^k得到的结果更优。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
long long n,ans,js;
void dfs(long long n){
    if(n==1||n==0)return;
    long long i;
    for( i=1;i*2<=n;i*=2);
    ans+=i-1;
    dfs(n-i);
}
int main(){
    scanf("%lld",&n);
    dfs(n);
    cout<<ans<<endl;
    return 0;
}

T2 LYK 快跑!

题目描述

LYK 陷进了一个迷宫! 这个迷宫是网格图形状的。 LYK 一开始在(1,1)(1,1)位置, 出口在(n,m)(n,m)。

而且这个迷宫里有很多怪兽,若第aa行第bb列有一个怪兽,且此时 LYK 处于第 cc行dd列,此时这个怪兽对它的威胁程度为|a-c|+|b-d|∣a?c∣+∣b?d∣。 LYK 想找到一条路径,使得它能从(1,1)(1,1)到达(n,m)(n,m),且在途中对它威胁程度最小的怪兽的威胁程度尽可能大。

当然若起点或者终点处有怪兽时,无论路径长什么样,威胁程度最小的怪兽始终=0=0。

输入输出格式

输入格式:

第一行两个数n,mn,m。

接下来nn行,每行mm个数,如果该数为00,则表示该位置没有怪兽,否则存在怪兽。

数据保证至少存在一个怪兽。

输出格式:

一个数表示答案。

输入输出样例

输入样例#1:

3 4
0 1 1 0
0 0 0 0
1 1 1 0

输出样例#1:

1

说明

对于20\%20%的数据n=1n=1。

对于40\%40%的数据n \leq 2n≤2。

对于60\%60%的数据n,m \leq 10n,m≤10。

对于80\%80%的数据n,m \leq100n,m≤100。

对于90\%90%的数据n,m \leq 1000n,m≤1000。

对于另外10\%10%的数据n,m \leq 1000n,m≤1000且怪兽数量\leq 100≤100。

题目大意:要求从(1,1)-->(n,m)的路径中距离最小的怪兽的距离最大值

题解:题目描述最小值最大应该是二分...可是我没想出来...

40搜索....(吐槽:只有40分不该呀.....

#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;

int n,m,cnt,ans,js;
int map[102][102],vis[102][102];
int mx[4]={0,1,0,-1},
    my[4]={1,0,-1,0};

struct WW{
    int x,y;
}w[10005];

struct T{
    int x,y,minl;
}s[50003];

int zs(int x){
    if(x<0)return -x;
    return x;
}

void slove(){
    queue<T>q;T s;s.x=1;s.y=1;s.minl=0x7fffffff;
    q.push(s);
    while(!q.empty()){
        T now;
        now=q.front();q.pop();
        vis[now.x][now.y]=0;
        int minl=0x7ffffff;
        for(int i=1;i<=cnt;i++){
            int xx=w[i].x,yy=w[i].y;
            minl=min(minl,zs(xx-now.x)+zs(yy-now.y));
        }
        if(minl<now.minl)now.minl=minl;js++;
        cout<<now.x<<" "<<now.y<<"  "<<now.minl<<endl;
        if(js==10){
            exit(0);
        }
        if(now.x==n&&now.y==m)ans=max(ans,now.minl);
        for(int i=0;i<4;i++){
            int xx=now.x+mx[i],yy=now.y+my[i];
            if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&!vis[xx][yy]){
                vis[xx][yy]=1;
                q.push((T){xx,yy,now.minl});
            }
        }
    }
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            int x;
            scanf("%d",&x);
            if(x)w[++cnt].x=i,w[cnt].y=j;
            if((i==1&&j==1&&x)||(i==n&&j==m&&x)||n==1){
                printf("0\n");
                return 0;
            }
        }
    }
    slove();
    printf("%d\n",ans);
    return 0;
}

正解:bfs预处理到每个非怪兽节点的最近的怪兽的距离,然后二分答案。

队列要开大点

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,l,r,ans,map[1002][1002],vis[1002][1002],qx[1000000],qy[1000000],b[1002][1002];
int mx[4]={0,1,-1,0},
    my[4]={1,0,0,-1};
int head=1,tail;
bool check(int limt){
    memset(vis,0,sizeof(vis));
    memset(qx,0,sizeof(qx));
    memset(qy,0,sizeof(qy));
    head=1;tail=0;
    qx[++tail]=1;qy[tail]=1;vis[1][1]=1;
    while(head<=tail){
        int nowx=qx[head],nowy=qy[head++];
        for(int i=0;i<4;i++){
            int xx=nowx+mx[i],yy=nowy+my[i];
            if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&!vis[xx][yy]&&b[xx][yy]>=limt){
                qx[++tail]=xx;qy[tail]=yy;
                vis[xx][yy]=1;
            }
        }
    }
    return vis[n][m];
}
void bfs(){
    while(head<=tail){
        int nowx=qx[head],nowy=qy[head++];
        for(int i=0;i<4;i++){
            int xx=nowx+mx[i],yy=nowy+my[i];
            if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&!vis[xx][yy]&&!b[xx][yy]&&!map[xx][yy]){
                b[xx][yy]=b[nowx][nowy]+1;
                vis[xx][yy]=1;
                qx[++tail]=xx;qy[tail]=yy;
            }
        }
    }
    l=0;r=n*m;
    while(l<=r){
        int mid=(l+r)>>1;
        if(check(mid)){
            ans=mid;l=mid+1;
        }
        else r=mid-1;
    }
    printf("%d\n",ans);
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&map[i][j]);
            if(map[i][j]){
                qx[++tail]=i;
                qy[tail]=j;
            }
        }
    }
    if(map[1][1]||map[n][m]||n==1){
        printf("0\n");
        return 0;
    }
    bfs();
    return 0;
}

T3 仙人掌(cactus)

题目描述

LYK 在冲刺清华集训(THUSC)于是它开始研究仙人掌,它想来和你一起分享它最近研究的结果。

如果在一个无向连通图中任意一条边至多属于一个简单环 (简单环的定义为每个点至多经过一次) ,且不存在自环,我们称这个图为仙人掌。

LYK 觉得仙人掌还是太简单了,于是它定义了属于自己的仙人掌。

定义一张图为美妙的仙人掌, 当且仅当这张图是一个仙人掌且对于任意两个不同的点i,ji,j,存在一条从ii出发到jj的路径,且经过的点的个数为|j-i|+1∣j?i∣+1个。 给定一张nn个点mm条边且没有自环的图,LYK 想知道美妙的仙人掌最多有多少条边。

数据保证整张图至少存在一个美妙的仙人掌。

输入输出格式

输入格式:

第一行两个数n,mn,m表示这张图的点数和边数。

接下来mm行,每行两个数u,vu,v表示存在一条连接u,vu,v的无向边。

输出格式:

一个数表示答案

输入输出样例

输入样例#1:

4 6
1 2
1 3
1 4
2 3
2 4
3 4

输出样例#1:

4

说明

对于20\%20%的数据n \leq 3n≤3。

对于40\%40%的数据n \leq 5n≤5。

对于60\%60%的数据n \leq 8n≤8。

对于80\%80%的数据n \leq 1000n≤1000。

对于100\%100%的数据n \leq 100000n≤100000且m \leq min(200000,n*(n-1)/2)m≤min(200000,n?(n?1)/2)。

样例解释

选择边1-21?2,1-31?3,2-32?3,3-43?4,能组成美妙的仙人掌,且不存在其它美妙仙人掌有超过44条边。

题解:30骗分(就问你强不强...

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n;
int main(){
    freopen("cactus.in","r",stdin);
    freopen("cactus.out","w",stdout);
    scanf("%d",&n);
    printf("%d\n",n);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

正解:由于i--j满足节点数等于|i-j|+1,那么i和i+1一定由一条边直接连着,剩下的边用线段覆盖解决。

#include<cstdio>
#include<algorithm>
#define maxn 100010
using namespace std;
int n,m,cnt;
struct node{
    int u,v;
    bool operator < (const node &x)const{
        return v<x.v;
    }
}e[maxn*2];
int init(){
    int x=0,f=1;char s=getchar();
    while(s<‘0‘||s>‘9‘){if(s==‘-‘)f=-1;s=getchar();}
    while(s>=‘0‘&&s<=‘9‘){x=x*10+s-‘0‘;s=getchar();}
    return x*f;
}
int main()
{
    freopen("cactus.in","r",stdin);
    freopen("cactus.out","w",stdout);
    n=init();m=init();
    int u,v;
    for(int i=1;i<=m;i++){
        u=init();v=init();
        if(u>v)swap(u,v);
        if(u!=v-1){
            e[++cnt].u=u;e[cnt].v=v;
        }
    }
    sort(e+1,e+1+cnt);
    int r=0,sum=0;
    for(int i=1;i<=cnt;i++)
        if(e[i].u>=r){
            sum++;r=e[i].v;
        }
    printf("%d\n",sum+n-1);
    return 0;
}
时间: 2024-08-10 23:30:57

9.17模拟赛的相关文章

【BZOJ】【2741】【FOTILE模拟赛】L

可持久化Trie+分块 神题……Orz zyf & lyd 首先我们先将整个序列搞个前缀异或和,那么某一段的异或和,就变成了两个数的异或和,所以我们就将询问[某个区间中最大的区间异或和]改变成[某个区间中 max(两个数的异或和)] 要是我们能将所有[l,r]的答案都预处理出来,那么我们就可以O(1)回答了:然而我们并不能. 一个常见的折中方案:分块! 这里先假设我们实现了一个神奇的函数ask(l,r,x),可以帮我们求出[l,r]这个区间中的数,与x最大的异或值. 我们不预处理所有的左端点,我

10.30 NFLS-NOIP模拟赛 解题报告

总结:今天去了NOIP模拟赛,其实是几道USACO的经典的题目,第一题和最后一题都有思路,第二题是我一开始写了个spfa,写了一半中途发现应该是矩阵乘法,然后没做完,然后就没有然后了!第二题的暴力都没码QAQ 现在我来写解题报告了,有点饿了QAQ.. 第一题 题目 1: 架设电话线 [Jeffrey Wang, 2007] 最近,Farmer John的奶牛们越来越不满于牛棚里一塌糊涂的电话服务,于 是,她们要求FJ把那些老旧的电话线换成性能更好的新电话线.新的电话线架设 在已有的N(2 <=

【题解】PAT团体程序设计天梯赛 - 模拟赛

由于本人愚笨,最后一题实在无力AC,于是只有前14题的题解Orz 总的来说,这次模拟赛的题目不算难,前14题基本上一眼就有思路,但是某些题写起来确实不太容易,编码复杂度有点高~ L1-1 N个数求和 设计一个分数类,重载加法运算符,注意要约分,用欧几里得算法求个最大公约数即可. 1 #include <cstdio> 2 3 long long abs(long long x) 4 { 5 return x < 0 ? -x : x; 6 } 7 8 long long gcd(long

[铁一中OI模拟赛]2017.8.19 Day1

T1 小Z的情书 题目链接 思考: 题目主要难度在于旋转后的位置如何,在手写了样例之后不难发现规律. #include <cstdio> #include <cstring> #define up(a,b,c) for(register int c=a;c<=b;++c) #define down(a,b,c) for(register int c=a;c>=b;--c) const int Maxn=1005; int n; bool Map[Maxn][Maxn],

bzoj2741: 【FOTILE模拟赛】L

2741: [FOTILE模拟赛]L Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 2679  Solved: 766[Submit][Status][Discuss] Description FOTILE得到了一个长为N的序列A,为了拯救地球,他希望知道某些区间内的最大的连续XOR和. 即对于一个询问,你需要求出max(Ai xor Ai+1 xor Ai+2 ... xor Aj),其中l<=i<=j<=r. 为了体现在线操作,对于一

140725模拟赛总结

A:hdu4847    字符串匹配第一想法是KMP,写了好长时间结果还TLE了-_-||,实际上用个简单的枚举判断就能解决.因为待验证的字符串"doge"很小.写A题的时候还被输入卡了半天.Tips1:输入至文件结尾(eof)的常用方法:     while (cin>>a)        //最常用的     while (cin.getline(s,30))    //按行读入前30个字符.空格也读入    getline(cin,s)        //和getli

NOIP模拟赛 6.29

2017-6-29 NOIP模拟赛 Problem 1 机器人(robot.cpp/c/pas) [题目描述] 早苗入手了最新的Gundam模型.最新款自然有着与以往不同的功能,那就是它能够自动行走,厉害吧. 早苗的新模型可以按照输入的命令进行移动,命令包括‘E’.‘S’.‘W’.‘N’四种,分别对应东南西北.执行某个命令时,它会向对应方向移动一个单位.作为新型机器人,它可以执行命令串.对于输入的命令串,每一秒它会按命令行动一次.执行完命令串的最后一个命令后,会自动从头开始循环.在0时刻时机器人

2017.11.25【NOIP提高组】模拟赛A组

2017.11.25[NOIP提高组]模拟赛A组 T1 3467. [NOIP2013模拟联考7]最长上升子序列(lis) T2 3468. [NOIP2013模拟联考7]OSU!(osu) T3 3472. [NOIP2013模拟联考8]匹配(match) T1 有转移方程f[i]=max{f[j]}+1,a[j]<a[i] 可以用线段树+离散化维护这个方程,因为涉及以往状态可以用主席树维护 打太丑爆空间了 Code 1 #include<cstdio> 2 #include<c

11.27 模拟赛

并没有人做的模拟赛... 出题人hx,,, T1:就是上一道矩阵乘法 数学题 T2: 一个数列中 一个区间满足,存在一个k(L <= k <= R),并且对于任意的i (L <= i <= R),ai都能被ak整除 这样的一个特殊区间 [L, R]价值为R - L 想知道序列中所有特殊区间的最大价值是多少,而有多少个这样的区间呢 这些区间又分别是哪些呢 输出每个区间的L 思路: 用两个ST表分别求一段区间的gcd和最小值 然后可以二分答案 check的时候枚举左端点,判断在这段区间