gym 101911

Posted -citywall123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了gym 101911相关的知识,希望对你有一定的参考价值。

A. Coffee Break

题意:每天有m小时,你喝咖啡需要花一小时,你想在n个时刻都喝过一次咖啡,老板规定连续喝咖啡的间隔必须是d以上,求最少需要多少天才能喝够n次咖啡,并输出每个时刻第几天喝。

 

题解:map+优先队列,用map将愿意喝咖啡的时间喝在第几天喝咖啡映射起来,优先队列遍历每个时刻和上一次喝的时间间隔是否大于d,若大于d,表示可以同一天喝,否则就在下一天喝

 

#include<iostream>
#include<algorithm>
#include<math.h>
#include<string>
#include<string.h>
#include<vector>
#include<utility>
#include<map>
#include<queue>
using namespace std;
map<int,int>m;
priority_queue<int,vector<int>,greater<int> >p;
int a[200005],b[200005];
int main()

    int n,t,d;
    scanf("%d%d%d",&n,&t,&d);
    for(int i=0;i<n;i++)
    
        scanf("%d",&b[i]);
        a[i]=b[i];
    
    sort(a,a+n);
    m[a[0]]=1;//最小的时间点一定是第一天就可以喝
    p.push(a[0]);
    int cnt=1;
    for(int i=1;i<n;i++)
    
        int now=p.top();
        if(a[i]-now>d)
        
            m[a[i]]=m[now];//可以同一天喝
            p.pop();
        
        else
            m[a[i]]=++cnt;//只能下一天喝
        p.push(a[i]);
    
    printf("%d\n",cnt);
    for(int i=0;i<n;i++)
    
        if(i==0)
            printf("%d",m[b[i]]);
        else
            printf(" %d",m[b[i]]);
    
    printf("\n");
    return 0;

 

B

 

 

 

C. Bacteria

题意:碗里有n个细菌,只有重量相同的细菌才可以合并在一起,合并后的细菌为两个细菌之后,为了把碗里的所有细菌合并成一个细菌,问最少还要向碗里增加几个细菌?若最后不能合并成一个细菌,输出-1,否则输出最少要加入的细菌个数

 

题解:优先队列逐个处理即可

#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<map>
#include<queue>
#define mx 0x3f3f3f3f
#define ll long long
using namespace std;
ll gcd(ll a, ll b)//最大公约数

    return b == 0 ? a : gcd(b, a % b);

ll lcm(ll a, ll b)//最小公倍数

    return a / gcd(a, b) * b;

priority_queue<ll,vector<ll>,greater<ll> > p;
int main()

    ll n;
    scanf("%lld",&n);
    for(int i=0;i<n;i++)
    
        ll temp;
        scanf("%lld",&temp);
        p.push(temp);
    
    ll flag=0,cnt=0;
    while(p.size()!=1)
    
        ll now=p.top();
        p.pop();
        if(p.size()==1)
        
            if(lcm(now,p.top())!=p.top())
            
                flag=1;
                break;
            
        
        if(now==p.top())
        
            now=now+p.top();
            p.pop();
            p.push(now);
        
        else
        
            cnt++;
            now=now*2;
            p.push(now);
        
    
    if(flag==1)
        printf("-1\n");
    else
        printf("%lld\n",cnt);
    return 0;

 

 

D、

题意:给你nn个数,你要给出不同的组合(a,b)(a,b)使得ab=A[i]ab=A[i],不能重复,但是(a,b)(a,b)和(b,a)(b,a)不同

 

题解:按照输入顺序枚举每一个数的因子,枚举到一个因子num[i]之后就退出,同时用vis[]反向标记一下这个数,下一次再次遇到这个数,就从上一次的因子num[i]+1继续枚举

用pair数组保存每一个数的一对因子

 

#include<iostream>
#include<algorithm>
#include<math.h>
#include<string>
#include<string.h>
#include<vector>
#include<utility>
#include<map>
using namespace std;
int vis[10000005],num[10000005];//vis反向标记,用num保存一个因子
pair<int,int>p[200005];
int a[200005];
int n;
int solve()

    for(int i=0;i<n;i++)
    
        if(vis[a[i]]==1)
        
            vis[a[i]]=0;
            p[i].first=a[i]/num[a[i]];
            p[i].second=num[a[i]];
            continue;
        
        int flag=0;
        for(int j=num[a[i]]+1;j<=sqrt(a[i]);j++)//对于每个数从最小的因子开始找,找到一对就退出,下一次再次遇到这个数就从num[a[i]]+1开始找因子
        
            if(a[i]%j==0)
            
                flag=1;
                num[a[i]]=j;//num只存一个因子即可
                if(a[i]/j!=j)
                    vis[a[i]]=1;//反向标记,例如第一次找到一组[1,3],用vis标记[3,1]的存在
                p[i].first=j;
                p[i].second=a[i]/j;
                break;//对于每个数,找到一对因子就退出
            
        
        if(flag==0)
            return 0;
    

    return 1;

int main()

    scanf("%d",&n);
    for(int i=0;i<n;i++)
    
        scanf("%d",&a[i]);
        num[a[i]]=0;//初始化a[i]的因子为0
    
    if(solve())
    
        printf("YES\n");
        for(int i=0;i<n;i++)
            printf("%d %d\n",p[i].first,p[i].second );
    
    else
        printf("NO\n");

 

F. Tickets

题意:有n次询问每次询问给一个数x,且x自动补全六位ABCDEF(可以有前导零),一个数的不幸运值=abs((D+E+F)-(A+B+C)),求出每个在这个数之前比自己不幸运值低的数的个数

 

题解:提前预处理所有数的不幸运值,然后统计比这个不幸运值低的数的个数

#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<map>
#define mx 0x3f3f3f3f
#define ll long long
using namespace std;
int a[1000005],cnt[300];
ll gcd(ll a, ll b)//最大公约数

    return b == 0 ? a : gcd(b, a % b);

int num(int i)

    int x=0, y=0;
    int xx=0,yy=0;
    x=i%1000;
    y=i/1000;
    while(x)
    
        int temp=x;
        x=x/10;
        xx=xx+temp%10;
    
    while(y)
    
        int temp=y;
        y=y/10;
        yy=yy+temp%10;
    
    return abs(xx-yy);


int main()

    int x;
    memset(cnt, 0, sizeof(cnt));
    for(int i=0; i<1000000; i++)
    
        a[i] = 0;
        x = num(i);
        cnt[x]++;
        for(int j=0; j<x; j++)
        
            a[i]+=cnt[j];
        
    
    int n;
    scanf("%d", &n);
    while(n--)
    
        scanf("%d", &x);
        printf("%d\n", a[x]);
    
    return 0;

 

H. Theater Square

题意:有一个矩形,挖掉一个小矩形之后用1*2的方块填充这个矩形,填充不完整的地方(会留有一些1*1)需要将1*2的方块打碎成两块用来填充,问打碎多少块1*2的方块

 

模拟即可

#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<map>
#define mx 0x3f3f3f3f
#define ll long long
using namespace std;
int a[1000005],cnt[300];
ll gcd(ll a, ll b)//最大公约数

    return b == 0 ? a : gcd(b, a % b);

int num(int i)

    int x=0, y=0;
    int xx=0,yy=0;
    x=i%1000;
    y=i/1000;
    while(x)
    
        int temp=x;
        x=x/10;
        xx=xx+temp%10;
    
    while(y)
    
        int temp=y;
        y=y/10;
        yy=yy+temp%10;
    
    return abs(xx-yy);


int main()

    int x;
    memset(cnt, 0, sizeof(cnt));
    for(int i=0; i<1000000; i++)
    
        a[i] = 0;
        x = num(i);
        cnt[x]++;
        for(int j=0; j<x; j++)
        
            a[i]+=cnt[j];
        
    
    int n;
    scanf("%d", &n);
    while(n--)
    
        scanf("%d", &x);
        printf("%d\n", a[x]);
    
    return 0;

 

I

题意:对一组本来连续的数,现在缺失了几个,问你最少缺失了几个

#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#define mx 0x3f3f3f3f
#define ll long long
using namespace std;
ll a[1005];
int main()

   ll n;
   scanf("%lld",&n);
   for(int i=0;i<n;i++)
    scanf("%lld",&a[i]);
    sort(a,a+n);
    int cnt=0;
    for(int i=1;i<n;i++)
        cnt=cnt+a[i]-a[i-1]-1;
    printf("%d\n",cnt);

 

J

题意:多少组w、h的比例满足x/y,要求w<=a&&h<=b

题解:将x/y化成最简分数,答案就是min(a/x,b/y);

#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#define mx 0x3f3f3f3f
#define ll long long
using namespace std;

ll gcd(ll a, ll b)//最大公约数

    return b == 0 ? a : gcd(b, a % b);

int main()

   ll a,b,x,y,xx;
   scanf("%lld%lld%lld%lld",&a,&b,&x,&y);
   xx=gcd(x,y);
   x=x/xx;
   y=y/xx;
   printf("%lld\n",min(a/x,b/y));

 

K

题意:可以将n个数进行区间分割要求每个区间的中位数>=m问最多可以分成多少个区间

题解:先将所有数从小到大排序,找到第一个满足条件的中位数,之后的所有数都满足条件

#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<map>
#include<queue>
#define mx 0x3f3f3f3f
#define ll long long
using namespace std;
ll gcd(ll a, ll b)//最大公约数

    return b == 0 ? a : gcd(b, a % b);

ll lcm(ll a, ll b)//最小公倍数

    return a / gcd(a, b) * b;

priority_queue<ll,vector<ll>,greater<ll> > p;
int a[5005];
int main()

    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++)
        scanf("%d",&a[i]);
    sort(a,a+n);
    int len=0,now=0,cnt=0;
    for(int i=0;i<n;i++)
    
        if(a[i]>=m)
            break;
        len++;
    

    for(int i=len;i<n;i++)
    
        if(a[i]>=m&&len==now)
        
            cnt++;
            cnt=cnt+n-(i+1);
            break;
        
        else
            now++;
    
    printf("%d\n",cnt);
    return 0;

 

以上是关于gym 101911的主要内容,如果未能解决你的问题,请参考以下文章

Gym - 101911B Glider(前缀和+二分)

CF Gym-101911A Coffee Break

gym 101911

CF Gym-101911K Medians and Partition

Gym - 101911A "Coffee Break"

Bacteria(优先队列)