AtCoder Beginner Contest 223

Posted MangataTS

tags:

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

A - Exact Price

题意

你有一个或者多个100的硬币,问你是否能完整凑出X元

思路

直接取余就行,特判一下0的情况

CODE

#include<bits/stdc++.h>
using namespace std;

const int N = 1e5+10;
int a[N];

int t,n;

int main()
{
	cin>>n;
	if(n == 0) puts("No");
	else {
		if(n % 100 == 0) puts("Yes");
		else puts("No");
	}
	
	return 0;
}

B - String Shifting

题意

给你一个字符串,你可以从该字符串的任意一个位置开始作为起始,然后以前一个位置为结束(将字符串想象成一个环),输出字典序最小的串和字典序最大的串

思路

  • 因为数据很小所以我们可以暴力查找,复杂度为 O ( N 2 ) O(N_2) O(N2)
  • 最小最大表示法,复杂度 O ( N ) O(N) O(N)

CODE

暴力

#include<bits/stdc++.h>
using namespace std;

int main()
{
	string s;
	cin>>s;
    string mi=s;
    string mx=s;
    for(int i=0;i<s.length();++i)
    {
        string x=string(s,i,s.length())+string(s,0,i);
        mi=min(mi,x);
        mx=max(mx,x);
    }
    cout<<mi<<endl;
    cout<<mx<<endl;
	return 0;
}

最大最小表示法

#include<bits/stdc++.h>
using namespace std;

const int N = 1e5+10;
char str[N];

int t,n;

int min_work()
{
    int n = strlen(str);
    int i = 0,j = 1, k = 0;
    while(i<n && j<n && k<n)
    {
        int t = str[(i+k)%n] - str[(j+k)%n] ;
        if(t == 0)
            k++;
        else
        {
            if(t>0)
                i+=k+1;
            else 
                j+=k+1;
            if(i==j)
                j++;
            k = 0;
        }
    }
    return i < j ? i : j;
}

int max_work()  //最大表示法
{
    int len = strlen(str);
    int i=0,j=1,k=0;
    while(i<len && j<len && k<len)
    {
        int t = str[(i+k)%len] - str[(j+k)%len];
        if(!t) k++;
        else
        {
            if(t>0) j = j+k+1;
            else i = i+k+1;
            if(i == j) j++;
            k = 0 ;
        }
    }
    return i<j?i:j;
}


int main()
{
	cin>>str;
	n = strlen(str);
	int l1 = min_work();
	int l2 = max_work();
	for(int i = 0;i < n; ++i) {
		putchar(str[l1]);
		l1++;
		l1 = l1 % n;
	}
	putchar('\\n');
	for(int i = 0;i < n; ++i) {
		putchar(str[l2]);
		l2++;
		l2 = l2 % n;
	}
	
	return 0;
}

C - Doukasen

题意

给你N段导火索,然后每段导火索的长度为 A i A_i Ai燃烧速度为 B i B_i Bi ,这N段导火索串联起来,然后再两端点燃,问你两团火相遇的时候距离左端点的距离是多少,至少保留五位小数

思路

先计算总共需要花费的时间,然后从左往右遍历过去,然后逐步计算即可

CODE

#include<bits/stdc++.h>
using namespace std;

const int N = 1e5+10;
double a[N];
double b[N],c[N];

int t,n;

int main()
{
	scanf("%d",&n);
	double sum_time = 0;
	for(int i = 0;i < n; ++i) {
		scanf("%lf%lf",&a[i],&b[i]);
		c[i] = a[i]/b[i];
		sum_time += c[i];
	}
	sum_time/=2;
	double sum_len = 0;
	int i = 0;
	for(;i < n; ++i) {
		if(sum_time >= c[i]) {
			sum_time -= c[i];
			sum_len += a[i];
		}
		else
			break;
	}
	sum_len += b[i] * sum_time;
	printf("%.7lf\\n",sum_len);
	return 0;
}

D - Restricted Permutation

题意

给你一个序列,找到满足条件的序列中字典序最小的序列

思路

拓扑排序

CODE

#include<bits/stdc++.h>
using namespace std;
const int N  = 200009;
int n, m, in[N];
struct Node
{
    int to, next;
} mp[N];
int head[N], num;
void add(int x, int y)
{
    mp[++num].to = y;
    mp[num].next = head[x];
    head[x] = num;
}
bool find(int x, int y)
{
    for (int i = head[x]; i; i = mp[i].next)
        if (mp[i].to == y) return true;
    return false;
}
void __sort()
{
    priority_queue<int, vector<int>, greater<int>> que;
    for (int i = 1; i <= n; ++i)
        if (!in[i])
            que.push(i);
    if (que.size() == 0)
    {
        puts("-1");
        return;
    }
    int ans[N]={0},cnt=0;
    while (!que.empty())
    {
        int p = que.top();
        que.pop();
        ans[++cnt]=p;
        for (int i = head[p]; i; i = mp[i].next)
        {
            int kk = mp[i].to;
            if (--in[kk] == 0)
                que.push(kk);
        }
    }
    if(cnt == n){
    	for(int i=1;i<=cnt;++i)
        {
            if(i!=1)
				putchar(' ');
            printf("%d",ans[i]);
        }
	}
	else
		puts("-1");
}
int main()
{
    scanf("%d %d", &n, &m);
    memset(head,0,sizeof head);
    memset(in,0,sizeof in);
    for (int i = 0; i < m; ++i)
    {
        int x, y;
        scanf("%d %d", &x, &y);
        if (find(x, y) == 0)
            add(x, y),in[y]++;
    }
    __sort();
    return 0;
}

E - Placing Rectangles

题意

给你一个长为X,宽为Y的矩形,然后三个面积分别为A,B,C的形状任意的矩形,问你是否能再第一个矩形中放下后面三个矩形(实际分配的面积可以大于后三个),且不能重叠

思路

思路就是从边入手,首先当后三个面积大于X*Y的时候直接输出No,然后我们假设放入的第一个矩形就会占据X行或者X列,然后我们再分别对剩下的两个矩形进行讨论,详情看代码

附上官方的题解证明:https://atcoder.jp/contests/abc223/editorial/2801

CODE

#include<bits/stdc++.h>
using namespace std;

#define ll long long
ll a[4];


bool f(ll X,ll Y,ll B,ll C) {
	if(X <= 0 || Y <= 0) return false;
	if(
		((B / X + ( B % X !=0) + C/X + (C % X != 0)) <= Y) || 
		((B / Y + (B % Y != 0) + C / Y + (C % Y != 0)) <= X)
	) 
		return true;
	else return false;
}
int main()
{
	ll X,Y;
	cin>>X>>Y;
	ll sum_area = 0;
	for(int i = 1;i <= 3; ++i) {
		cin>>a[i];
		sum_area+=a[i];
	}
	if(sum_area > X * Y) {
		puts("No");
		return 0;
	}
	else {
		bool fg = false;
		fg |= f(X - a[1]/Y - (a[1] % Y != 0),Y,a[2],a[3]);
		fg |= f(X - a[2]/Y - (a[2] % Y != 0),Y,a[1],a[3]);
		fg |= f(X - a[3]/Y - (a[3] % Y != 0),Y,a[1],a[2]);
		
		fg |= f(Y - a[1]/X - (a[1] % X != 0),X,a[2],a[3]);
		fg |= f(Y - a[2]/X - (a[2] % X != 0),X,a[1],a[3]);
		fg |= f(Y - a[3]/X - (a[3] % X != 0),X,a[1],a[2]);
		if(fg) puts("Yes");
		else puts("No");
	}
	return 0;
}

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

AtCoder Beginner Contest 234

AtCoder Beginner Contest 115 题解

AtCoder Beginner Contest 154 题解

AtCoder Beginner Contest 103

AtCoder Beginner Contest 228

AtCoder Beginner Contest 242