2019年9月7日(贪心专题考试)

Posted alanallen21love28

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2019年9月7日(贪心专题考试)相关的知识,希望对你有一定的参考价值。

难受,炸(long~long),(QwQ)

(prob1:Maximal~GCD)

一句话:注意判炸(long~long)

没公约数的情况不用说了,若有设其为(p),很明显(n)(p)的倍数,此时可以将序列的和化为(n/p)(p)的和,又(n/p)个最少为(k*(k+1)>>1)个,所以就得到了(n/p)的下界,则(p)的上界为(frac{n}{k*(k+1)>>1}),只需求在该界之下的最大的(n)的因数即可求出(p)的最大值。

(tmp)之下第一个(n)的倍数可以这么求:

inline long long chu(long long n,long long k)
{
    long long g=1;
    for(;n%k;k=n/k+g,g^=1);
    return g?k:n/k;
}  

总的代码:

#include<iostream>
using namespace std;
inline long long read()
{
    long long x=0;
    char ch=getchar();
    for(;!isalnum(ch);ch=getchar());
    for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
    return x;
}
inline long long need(long long m,long long f)
{
    long long ans=2*m-f*f+f;
    ans=ans/(2*f);
    return ans;
}
inline long long chu(long long n,long long k)
{
    long long g=1;
    for(;n%k;k=n/k+g,g^=1);
    return g?k:n/k;
}
int main()
{
//  freopen("out.cpp","w",stdout);
    long long n=read(),k=read();
    long long tmp=need(n,k);
    tmp=min(tmp,n/(k*(k+1)>>1));
    if(tmp<=0||k>2e5) puts("-1"),exit(0);
    long long p=chu(n,tmp);
    long long t=n-(k*(k+1)>>1)*p;
    for(long long j=1;j<=k-1;++j) printf("%lld ",p*j);
    printf("%lld
",t+k*p);
    return 0;
}

(prob2:Artem~and~Array)

明显易知,在一个(2* 2)的矩阵中,若存且仅存在一个("* "),那么,这个("* ")必须变成".",(bfs)一下就好了

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
#define in read()
#define re register
#define fur(i,a,b) for(re int i=a;i<=b;++i)
#define fdr(i,a,b) for(re int i=a;i>=b;--i)
#define jinitaimei signed
#define nm make_pair
#define pr pair<int,int>
//#define int long long
inline int read()
{
    int x=0;
    char ch=getchar();
    for(;!isalnum(ch);ch=getchar());
    for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
    return x;
}
const int xx=2e3+10;
int wall[xx][xx];
int n,m,name=0;
char op[xx];
queue<pr>q;
inline void bfs()
{
    while(!q.empty())
    {
        int x=q.front().first,y=q.front().second;
        q.pop();
        name=wall[x+1][y+1]+wall[x][y+1]+wall[x+1][y];
        if(name==1&&y<m&&x<n)
        {
            if(wall[x+1][y+1]) wall[x+1][y+1]=0,q.push(nm(x+1,y+1));
            if(wall[x+1][y]) wall[x+1][y]=0,q.push(nm(x+1,y));
            if(wall[x][y+1]) wall[x][y+1]=0,q.push(nm(x,y+1));
        }
        name=wall[x+1][y-1]+wall[x][y-1]+wall[x+1][y];
        if(name==1&&y>1&&x<n)
        {
            if(wall[x+1][y-1]) wall[x+1][y-1]=0,q.push(nm(x+1,y-1));
            if(wall[x+1][y]) wall[x+1][y]=0,q.push(nm(x+1,y));
            if(wall[x][y-1]) wall[x][y-1]=0,q.push(nm(x,y-1));
        }
        name=wall[x-1][y+1]+wall[x][y+1]+wall[x-1][y];
        if(name==1&&x>1&&y<m)
        {
            if(wall[x-1][y+1]) wall[x-1][y+1]=0,q.push(nm(x-1,y+1));
            if(wall[x-1][y]) wall[x-1][y]=0,q.push(nm(x-1,y));
            if(wall[x][y+1]) wall[x][y+1]=0,q.push(nm(x,y+1));
        }
        name=wall[x-1][y-1]+wall[x-1][y]+wall[x][y-1];
        if(name==1&&x>1&&y>1)
        {
            if(wall[x-1][y-1]) wall[x-1][y-1]=0,q.push(nm(x-1,y-1));
            if(wall[x-1][y]) wall[x-1][y]=0,q.push(nm(x-1,y));
            if(wall[x][y-1]) wall[x][y-1]=0,q.push(nm(x,y-1));
        }
    }
}
jinitaimei main()
{
    n=in,m=in;
    fur(i,1,n)
    {
        scanf("%s",op);
        fur(j,1,m)
        {
            wall[i][j]=op[j-1]=='*'?1:0;
            if(!wall[i][j]) q.push(nm(i,j));
        }
    }
    bfs();
    fur(i,1,n)
    {
        fur(j,1,m) printf("%c",wall[i][j]?'*':'.');
        cout<<endl;
    }
    return 0;
}

(prob3:Students'~Revenge)

若将所有任务按(b)为第一关键字排序,那么主席肯定会选我们选中的(p)个任务中的靠后(k)个,先得到这后(k)(sum a)的最大值,再在前面(p-k)个中取到(max(sum b))即可

#include<iostream>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
#define in read()
#define re register
#define fur(i,a,b) for(re int i=a;i<=b;++i)
#define fdr(i,a,b) for(re int i=a;i>=b;--i)
#define int long long
#define pr pair<int,int>
#define hp __gnu_pbds::priority_queue<pr,greater<pr> >
#define nm make_pair
hp q;
inline int read()
{
    int x=0;
    char ch=getchar();
    for(;!isalnum(ch);ch=getchar());
    for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
    return x;
}
const int xx=1e5+10;
struct person
{
    int a,b;
    int id;
}m[xx];
bool choose[xx];
inline bool cmp(person x,person y)
{
    return (x.b^y.b)?(x.b<y.b):(x.a>y.a);
}
main()
{
    int n=in,l=in,k=in,Min=n-k+1;
    fur(i,1,n) m[i].a=in,m[i].b=in,m[i].id=i;
    sort(m+1,m+n+1,cmp);
    fdr(i,n,n-k+1) choose[i]=true,q.push(nm(m[i].a,i));
    l=l-k;
    fdr(i,n-k,l+1) if(m[i].a>q.top().first)
    {
         choose[q.top().second]=false;
         q.pop();
         q.push(nm(m[i].a,i));
         Min=i;
    }
    while(!q.empty()) printf("%lld ",m[q.top().second].id),q.pop();
    while(l--) printf("%lld ",m[--Min].id);
    puts("");
    return 0;
}

(prob4:Ball~Coloring)

先令所有二元组的(x)小于(y),在两边得到(Rmax,Rmin,Lmax,Lmin),此为第一种情况,

再将序列按(x)为关键字排序,从小到大除最大的(x)所在的二元组外,其他二元组一一交换,可以证明,答案一定在其中

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define in read()
#define re register
#define fur(i,a,b) for(re int i=a;i<=b;++i)
#define fdr(i,a,b) for(re int i=a;i>=b;--i)
#define cl(a,b) memset(a,b,sizeof(a))
#define jinitaimei signed
#define int long long
inline int read()
{
    int x=0;
    char ch=getchar();
    for(;!isalnum(ch);ch=getchar());
    for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
    return x;
}
const int xx=2e5+101;
struct person
{
    int x,y;
}m[xx];
inline bool cmp(person a,person b)
{
    return a.x<b.x;
}
jinitaimei main()
{
    int n=in,xmax=0,xmin=2e18,ymax=0,ymin=2e18;
    fur(i,1,n)
    {
        m[i].x=in,m[i].y=in;
        if(m[i].x>m[i].y) swap(m[i].x,m[i].y);
        xmax=max(xmax,m[i].x);
        xmin=min(xmin,m[i].x);
        ymax=max(ymax,m[i].y);
        ymin=min(ymin,m[i].y);
    }
    int ans=(xmax-xmin)*(ymax-ymin);
    sort(m+1,m+n+1,cmp);
    ymin=xmin;
    int maxl=m[1].y,minl=m[1].y,ans2=2e18;
    fur(i,2,n-1)
    {
        maxl=max(maxl,m[i].y);
        minl=min(minl,m[i].y);
        ans2=min(ans2,max(maxl,m[n].x)-min(minl,m[i+1].x));
    }
    if(n>2) ans2*=(ymax-ymin);
    ans=min(ans,ans2);
    cout<<ans<<endl;
    return 0;
}

(prob5:Ant~Man)

可以证明,将从(1)(n)的所有非(s)(t)的点局部最优地插入(s)(t)的间隔中可以得到全局最优解

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define in read()
#define re register
#define fur(i,a,b) for(re int i=a;i<=b;++i)
#define fdr(i,a,b) for(re int i=a;i>=b;--i)
#define cl(a,b) memset(a,b,sizeof(a))
#define jinitaimei signed
#define int long long
inline int read()
{
    int x=0;
    char ch=getchar();
    for(;!isalnum(ch);ch=getchar());
    for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
    return x;
}
const int xx=5e3+101;
int nxt[xx];
int x[xx],a[xx],b[xx],c[xx],d[xx];
inline int dis(int xa,int ya)
{
    if(ya<xa) return x[xa]-x[ya]+c[xa]+b[ya];
    return x[ya]-x[xa]+d[xa]+a[ya];
}
jinitaimei main()
{
    int n=in,s=in,t=in;
    fur(i,1,n) x[i]=in;
    fur(i,1,n) a[i]=in;
    fur(i,1,n) b[i]=in;
    fur(i,1,n) c[i]=in;
    fur(i,1,n) d[i]=in;
    nxt[s]=t;nxt[t]=0;
    int ans=dis(s,t);
    fur(i,1,n) if(i!=s&&i!=t)
    {
        int mn=2e18,tmp=s,j=s;
        while(nxt[j])
        {
            if(dis(j,i)+dis(i,nxt[j])-dis(j,nxt[j])<=mn)
            {
                mn=dis(j,i)+dis(i,nxt[j])-dis(j,nxt[j]);
                tmp=j;
            }
            j=nxt[j];
        }
        ans+=mn;
        nxt[i]=nxt[tmp];
        nxt[tmp]=i;
    }
    printf("%lld
",ans);
    return 0;
}

以上是关于2019年9月7日(贪心专题考试)的主要内容,如果未能解决你的问题,请参考以下文章

;~ 小部分AutoHotkey源代码片段测试模板2019年10月9日.ahk

系统架构设计师考试介绍

生物信息数据处理与Perl语言编程应用专题培训班通知(10月9-11日)

消防工程师

关于2019年3月30日项目管理资格认证考试的报名通知

2020年9月全国计算机等级考试C语言冲刺练习(9月13日)