欢迎来到endl的博客hhh☀☾☽♡♥

浏览器标题切换
把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

20200728模拟

 

题目

覆盖

分组

部落

命名

cover.cpp

grouping.cpp

tribal.cpp

内存

128M

128M

128M

时限

1s

1s

1s

 

1、覆盖(cover.cpp)(源自洛谷P1990 覆盖墙壁

题目描述

你有一个长为N宽为2的墙壁,给你两种砖头:一个长2宽1,另一个是L型覆盖3个单元的砖头。如下图:

0  0
0  00

砖头可以旋转,两种砖头可以无限制提供。你的任务是计算用这两种来覆盖N*2的墙壁的覆盖方法。例如一个2*3的墙可以有5种覆盖方法,如下:

012 002 011 001 011  
012 112 022 011 001

注意可以使用两种砖头混合起来覆盖,如2*4的墙可以这样覆盖:

0112
0012

给定N,要求计算2*N的墙壁的覆盖方法。由于结果很大,所以只要求输出最后4位。例如2*13的覆盖方法为13465,只需输出3465即可。如果答案少于4位,就直接输出就可以,不用加0,如N=3,时输出5。

输入格式

一个整数N(1<=N<=1000000),表示墙壁的长。

输出格式

输出覆盖方法的最后4位,如果不足4位就输出整个答案。

输入输出样例

输入

13

输出

3465

 

O(≧口≦)O推了半天没搞出递推式 0分

#include<bits/stdc++.h>
#define R register int
#define ll long long
using namespace std;
const int N=1e6+5,mod=10000;
int n,f[N];
int read()
{
    int f=1;char ch;
    while((ch=getchar())<'0'||ch>'9')if(ch=='-')f=-1;
    int res=ch-'0';
    while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-'0';
    return res*f;
}
void write(int x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
int main()
{
    //freopen("cover.in","r",stdin);
    //freopen("cover.out","w",stdout);
    n=read();
    //f[0]=1;
    f[1]=1;f[2]=2;f[3]=5;
    if(n==1)putchar('1');
    else if(n==2)putchar('2');
    else if(n==3)putchar('5');
    else
    {
        for(R i=4;i<=n;i++)f[i]=(2*f[i-1]+f[i-3])%mod;
        write(f[n]);
    }
    
    return 0;
}
正解

 

2、分组(grouping.cpp(源自洛谷P4447 [AHOI2018初中组]分组

题目描述

小可可的学校信息组总共有n 个队员,每个人都有一个实力值a[i]。现在,一年一度的编程大赛就要到了,小可可的学校获得了若干个参赛名额,教练决定把学校信息组的n个队员分成若干个小组去参加这场比赛。

但是每个队员都不会愿意与实力跟自己过于悬殊的队员组队,于是要求分成的每个小组的队员实力值连续,同时,一个队不需要两个实力相同的选手。举个例子:[1, 2, 3, 4, 5]是合法的分组方案,因为实力值连续;[1, 2, 3, 5]不是合法的分组方案,因为实力值不连续;[0, 1, 1, 2]同样不是合法的分组方案,因为出现了两个实力值为1 的选手。

如果有小组内人数太少,就会因为时间不够而无法获得高分,于是小可可想让你给出一个合法的分组方案,满足所有人都恰好分到一个小组,使得人数最少的组人数最多,输出人数最少的组人数的最大值。

注意:实力值可能是负数,分组的数量没有限制。

输入格式

输入有两行:

第一行一个正整数n,表示队员数量。
第二行有n 个整数,第i 个整数a[i]表示第i 个队员的实力。

输出格式

输出一行,包括一个正整数,表示人数最少的组的人数最大值。

输入输出样例

输入

7
4 5 2 3 -4 -3 -5

输出

3

说明/提示

【样例解释】 分为2 组,一组的队员实力值是{4, 5, 2, 3}一组是{-4, -3, -5}其中最小的组人数为3,可以发现没有比3 更优的分法了。

【数据范围】

对于100%的数据满足:1≤n≤100000,|a[i]|≤10^9。

本题共10 个测试点,编号为1~10,每个测试点额外保证如下:

1~2 n≤6, 1≤a[i]≤100
3~4 n≤1000, 1≤a[i]≤10^5且a[i]互不相同
5~6 n≤100000, a[i]互不相同
7~8 n≤100000, 1≤a[i]≤10^5
9~10 n≤100000, |a[i]|≤10^9


 

 

#include<bits/stdc++.h>
#define R register int
#define ll long long
using namespace std;
const int N=1e6+5,inf=0x3f3f3f3f;
int n,a[N];
int read()
{
    int f=1;char ch;
    while((ch=getchar())<'0'||ch>'9')if(ch=='-')f=-1;
    int res=ch-'0';
    while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-'0';
    return res*f;
}
void write(int x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
int main()
{
    //freopen("grouping.in","r",stdin);
    //freopen("grouping.out","w",stdout);
    n=read();
    for(R i=1;i<=n;i++)a[i]=read();
    sort(a+1,a+1+n);
    int num=1,ans=inf;
    for(R i=2;i<=n;i++)
    {
        
        if(a[i-1]+1==a[i])num++;
        else if(a[i-1]+1!=a[i])
        {
            ans=min(ans,num);
            num=1;
        }
    }
    write(ans);
    return 0;
}
没考虑最后一个点的错误贪心40分代码
#include<bits/stdc++.h>
#define R register int
#define ll long long
using namespace std;
const int N=1e6+5,inf=0x3f3f3f3f;
int n,a[N];
int read()
{
    int f=1;char ch;
    while((ch=getchar())<'0'||ch>'9')if(ch=='-')f=-1;
    int res=ch-'0';
    while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-'0';
    return res*f;
}
void write(int x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
int main()
{
    //freopen("grouping.in","r",stdin);
    //freopen("grouping.out","w",stdout);
    n=read();
    for(R i=1;i<=n;i++)a[i]=read();
    sort(a+1,a+1+n);
    int num=1,ans=inf;
    for(R i=2;i<=n+1;i++)
    {
        
        if(a[i-1]+1==a[i])num++;
        else 
        {
            ans=min(ans,num);
            num=1;
        }
    }
    write(ans);
    return 0;
}
贪心60分代码
#include<bits/stdc++.h>
#define R register int
#define ll long long
using namespace std;
const int N=1e6+5,inf=0x3f3f3f3f;
int n,a[N];
int read()
{
    int f=1;char ch;
    while((ch=getchar())<'0'||ch>'9')if(ch=='-')f=-1;
    int res=ch-'0';
    while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-'0';
    return res*f;
}
void write(int x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
struct node{
    int la,num;
}b[N];
int main()
{
    //freopen("grouping.in","r",stdin);
    //freopen("grouping.out","w",stdout);
    n=read();
    for(R i=1;i<=n;i++)a[i]=read();
    sort(a+1,a+1+n);
    int cnt=0;
    for(R i=1;i<=n;i++)
    {
        bool flag=false;
        for(R j=cnt;j;j--)
        {
            if(b[j].la+1==a[i])
            {
                flag=true;
                b[j].num++;
                b[j].la++;
                break;
            }
        }
        if(!flag)
        {
            b[++cnt].num=1;
            b[cnt].la=a[i];
        }
    }
    int ans=inf;
    for(R i=1;i<=cnt;i++)ans=min(ans,b[i].num);
    write(ans);
    return 0;
}
AC代码

 

3、部落(tribal.cpp(源自洛谷P4047 [JSOI2010]部落划分

题目描述

聪聪研究发现,荒岛野人总是过着群居的生活,但是,并不是整个荒岛上的所有野人都属于同一个部落,野人们总是拉帮结派形成属于自己的部落,不同的部落之间则经常发生争斗。只是,这一切都成为谜团了——聪聪根本就不知道部落究竟是如何分布的。

不过好消息是,聪聪得到了一份荒岛的地图。地图上标注了 n个野人居住的地点(可以看作是平面上的坐标)。我们知道,同一个部落的野人总是生活在附近。我们把两个部落的距离,定义为部落中距离最近的那两个居住点的距离。聪聪还获得了一个有意义的信息——这些野人总共被分为了 k 个部落!这真是个好消息。聪聪希望从这些信息里挖掘出所有部落的详细信息。他正在尝试这样一种算法:

对于任意一种部落划分的方法,都能够求出两个部落之间的距离,聪聪希望求出一种部落划分的方法,使靠得最近的两个部落尽可能远离。

例如,下面的左图表示了一个好的划分,而右图则不是。请你编程帮助聪聪解决这个难题。

 

输入格式

输入文件第一行包含两个整数 n和 k,分别代表了野人居住点的数量和部落的数量。

接下来 n行,每行包含两个整数 x,y,描述了一个居住点的坐标。

输出格式

输出一行一个实数,为最优划分时,最近的两个部落的距离,精确到小数点后两位。

输入输出样例

输入 #1

4 2
0 0
0 1
1 1
1 0

输出 #1

1.00

输入 #2

9 3
2 2
2 3
3 2
3 3
3 5
3 6
4 6
6 2
6 3

输出 #2

2.00

说明/提示

数据规模与约定

对于 100% 的数据,保证 2≤kn≤10^3, 0≤x,y≤10^4。

 


 

#include<bits/stdc++.h>
#define R register int
#define ll long long
using namespace std;
const int N=1e6+5;
int n,k,t,fa[1005];
struct node{
    int x,y;
}a[1005];
struct Node{
    int x,y;
    double dis;
    /*bool operator <(const Node &p)const
    {
        return dis<p.dis;
    }*/
}b[N];
int read()
{
    int f=1;char ch;
    while((ch=getchar())<'0'||ch>'9')if(ch=='-')f=-1;
    int res=ch-'0';
    while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-'0';
    return res*f;
}
void write(int x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
int find(int x)
{
    if(fa[x]!=x)return fa[x]=find(fa[x]);
    return x;
}
int main()
{
    //freopen("tribal.in","r",stdin);
    //freopen("tribal.out","w",stdout);
    n=read();k=read();
    for(R i=1;i<=n;i++)
    {
        a[i].x=read();a[i].y=read();
    }
    //double ma=0;
    for(R i=1;i<=n;i++)
    {
        for(R j=1;j<i;j++)
        //if(i!=j)
        {
            b[++t].dis=sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y));
            b[t].x=i;b[t].y=j;
            //if(b[t].dis>ma)ma=b[t].dis;
            //printf("g[%d][%d]=%lf\n",i,j,g[i][j]);
        }
    }
    //sort(b+1,b+1+t);
    double l=0,r=100000000;//r=ma;
    while(l+0.0001<r)
    {
        double mid=(l+r)/2;
        //cout<<mid<<endl;
        int num=0;
        for(R i=1;i<=n;i++)fa[i]=i;
        for(R i=1;i<=t;i++)
        {
            if(b[i].dis>mid)continue;
            int aa=b[i].x,bb=b[i].y;
            int faa=find(aa),fbb=find(bb);
            if(faa!=fbb)fa[fbb]=faa;
            //printf("find(%d)=%d,find(%d)=%d\n",aa,faa,bb,fbb);
        }
        for(R i=1;i<=n;i++)
        {
            if(fa[i]==i)num++;
        }
        //cout<<num<<endl;
        if(num>=k)l=mid;
        else r=mid;
    }
    printf("%.2lf",l);
    return 0;
}
/*if(judge(d[mid]))l=mid;
        else r=mid-1;*/
AC代码

 

posted @ 2020-07-29 11:02  endl\n  阅读(299)  评论(0编辑  收藏  举报