码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2019-09-10 20:59:50      阅读:136      评论:0      收藏:0      [点我收藏+]

标签:als   www   ns2   pair   lmin   cout   reg   cond   mat   

难受,炸\(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\n",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\n",ans);
    return 0;
}

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

标签:als   www   ns2   pair   lmin   cout   reg   cond   mat   

原文地址:https://www.cnblogs.com/ALANALLEN21LOVE28/p/11502657.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!