[AtCoder Beginner Contest 131]A~E简要解析

【因中考失踪人口回归】

咳咳,进入正题~~

A题 Security

题目大意
就是输入一个四位数,看有没有连续的俩数字。
code

#include
int main()
{
	int a,b,c,d;
	scanf("%01d %01d %01d %01d",&a,&b,&c,&d);
	if(a==b || b==c || c==d)
		printf("Bad\n");
	else
		printf("Good\n");
	return 0;
}

B题 Bite Eating

题目大意
给两个数字NL,从L开始数N个数,然后减去绝对值最小的数再输出。
(我会说我因为看不懂题然后卡了半个小时???)
code

#include
#include
using namespace std;

int main()
{
	int n,l;
	scanf("%d %d",&n,&l);
	int f,e;
	f=l;e=l+n-1;
	int ans=(f+e)*(e-f+1)/2;
	if(f<=0 && e>=0)
		printf("%d\n",ans);
	else if(f<=0 && e<=0)
		printf("%d\n",ans-e);
	else
		printf("%d\n",ans-f);
	return 0;
}

C题 Anti-Division

题目大意
给你abcd四个数,然后在 [a,b] 中查找 不是,c和d的倍数的数的个数(是不是有一点绕。。。)

简要解析
(为什么AB题不写,因为太简单了啊)
这个题用各种取模整除,做了好久。。。。
想法如下:
[AtCoder Beginner Contest 131]A~E简要解析_第1张图片
然后在 A` 和 B` 中去数有多少个c的倍数(找d同c)。。。。(思维极度复杂)
再容斥原理加回来公共部分。
关键是做了很久还WA了两遍。。。

然后。。。。同学说,直接除了然后减。。。。。(我:“啥??”)

同学:“除了之后就是它前面的c或d的因数个数,直接相减就是中间的了。”

我:“。。。。。。”

code

//Mine
#include
#include
using namespace std;

long long gcd(long long x,long long y)
{
	if(!y) return x;
	return gcd(y,x%y);
}

int main()
{
	long long a,b,c,d;
	scanf("%lld %lld %lld %lld",&a,&b,&c,&d);
	long long e=c*d/gcd(c,d);a--;
	long long ans=(b-a+1)-((b-(b%c))-(a-(a%c)))/c-1-((b-(b%d))-(a-(a%d)))/d-1+((b-(b%e))-(a-(a%e)))/e+1;
	printf("%lld\n",ans);
	return 0;
}

//Better method
#include
#include
using namespace std;

long long gcd(long long x,long long y)
{
	if(!y) return x;
	return gcd(y,x%y);
}

int main()
{
	long long a,b,c,d;
	scanf("%lld %lld %lld %lld",&a,&b,&c,&d);
	long long e=c*d/gcd(c,d);a--;
	long long ans=(b-a)-b/c+a/c-b/d+a/d+b/e-a/e;
	printf("%lld\n",ans);
	return 0;
}

D题 Megalomania

题目大意
(这不就是一道贪心题吗。。。)
N个工作,每一件需要Ai的时间,截止时间(需要在这个时间或之前完成)是Bi,问能不能在每一件工作截止时间前完成。可以的话输出"Yes",否则是"No"。(注意这个大小写!)

简要解析
依据每一个工作的结束时间由小到大排序,相同时,按其花费时间由小到大排序。

理解:当然是先做要紧的事情啊,然后同样要紧的事情当然是先做能尽快完成的呀

然后再按这个顺序做就OK了。

code

#include
#include
using namespace std;

const int N=200000;
int n;
struct node
{
	int a,b;
}k[N+5];
inline bool _cmp(node a,node b)
{
	return a.b != b.b ? a.b < b.b : a.a < b.a;
}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d %d",&k[i].a,&k[i].b);
	sort(k+1,k+n+1,_cmp);
	
	int t=0;
	for(int i=1;i<=n;i++)
	{
		if(t+k[i].a<=k[i].b)
			t+=k[i].a;	
		else
		{
			printf("No\n");
			return 0;
		}
	}
	printf("Yes\n");
	return 0;
}

E题 Friendships

题目大意
构造数据,使用N个点,使得其中有恰好K对点的距离恰好为2。
然后输出你构造的边数和每一条边(每条边长度为1)

简要解析
其实一开始要我做,我是懵逼的,这个怎么构造???完全不知道好吧。。。
后来知道了一个叫做 “菊花图” 的东西(仿佛打开了新世界的大门。。。)

如图:
[AtCoder Beginner Contest 131]A~E简要解析_第2张图片
好的,现在我们可以很明显地发现,这里面距离为2的点对有10对,然后进一步发现其实就是 C n − 1 2 C_{n-1}^{2} Cn12
嗯,然后呢,就可以直接计算能不能实现构造(就是看输不输出-1)了。。

同学:“那怎么删边呢?”
嗯,是个好问题!
我们删边就直接将除1以外的点连边就好了呀,每次只会影响一对点,所以点对数就减1。
code

#include
#include

#define X first
#define Y second

using namespace std;

const int N=100;
int n,k;

int cnt;
pair Edge[N*N/2];

void Print()
{
	printf("%d\n",cnt);
	for(int k=1;k<=cnt;k++)
		printf("%d %d\n",Edge[k].X,Edge[k].Y);
}

int main()
{
	scanf("%d %d",&n,&k);
	int num=(n-1)*(n-2)/2;
	if(k>num)
	{
		printf("-1\n");
		return 0;
	}
	
	for(int i=2;i<=n;i++)
		Edge[++cnt]=make_pair(1,i);
	if(num>k)
	{
		for(int i=2;i<=n;i++)
			for(int j=i+1;j<=n;j++)
			{
				Edge[++cnt]=make_pair(i,j);
				if( --num == k )
				{
					Print();
					return 0;
				}
			}
	}
	Print();
	return 0;
}

结语

这次考得实在不好,可能是因为好久没码代码了吧,就权当热身了,下次一定不能这样了。
博客捏,有点点花时间,不过写一写加深印象也值得吧。。。

你可能感兴趣的:([AtCoder Beginner Contest 131]A~E简要解析)