AtCoder Beginner Contest 238

Posted MangataTS

tags:

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

比赛链接

https://atcoder.jp/contests/abc238

A - Exponential or Quadratic(签到+数学)

题意

如果 2 n > n 2 2^n > n^2 2n>n2那么就输出Yes否则输出No

思路

小学生都知道特判一下2、3、4三个数就好了,其他都输出Yes即可

代码

#include<bits/stdc++.h>
using namespace std;
//----------------自定义部分----------------
#define ll long long
#define int long long
#define mod 1000000007
#define endl "\\n"
#define PII pair<int,int>
#define INF 0x3f3f3f3f

int dx[4]=0,-1,0,1,dy[4]=-1,0,1,0;

ll ksm(ll a,ll b) 
	ll ans = 1;
	for(;b;b>>=1LL) 
		if(b & 1) ans = ans * a % mod;
		a = a * a % mod;
	
	return ans;


ll lowbit(ll x)return -x & x;

const int N = 2e6+10;
//----------------自定义部分----------------
int n,m,q,a[N];

signed main()

	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout.tie(nullptr);
	cin>>n;
	if(n == 2 || n == 3 || n == 4) cout<<"No"<<endl;
	else cout<<"Yes"<<endl;
	
	return 0;

B - Pizza(桶排思想)

题意

首先在12点钟方向划一刀,然后有一个数组A,里面存放的是每次旋转的角度,我们每次顺时针旋转 A [ i ] A[i] A[i]度,然后再在当前的12点钟方向划一刀,问你最后相邻两刀的最大角度差是多少

思路

因为圆的面积就360度,所以我们开一个这么大的数组或者map容器,然后记录下当前的12点钟的角度,一开始是0度,每次旋转 A [ i ] A[i] A[i]度,直接累加就好了,最后我们再对这些角度排序再计算一下差值的最大值即可,注意由于是圆,有可能是最小角度到最大角度

代码

#include<bits/stdc++.h>
using namespace std;
//----------------自定义部分----------------
#define ll long long
#define mod 360
#define endl "\\n"
#define PII pair<int,int>
#define INF 0x3f3f3f3f

int dx[4]=0,-1,0,1,dy[4]=-1,0,1,0;

ll ksm(ll a,ll b) 
	ll ans = 1;
	for(;b;b>>=1LL) 
		if(b & 1) ans = ans * a % mod;
		a = a * a % mod;
	
	return ans;


ll lowbit(ll x)return -x & x;

const int N = 2e6+10;
//----------------自定义部分----------------
int n,m,q,a[N];
map<int,bool> vis;

int main()

	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout.tie(nullptr);
	cin>>n;
	for(int i = 1;i <= n; ++i) cin>>a[i];
	vis[0] = true;
	int loc = 0;
	for(int i = 1;i <= n; ++i) 
		loc += a[i];
		loc %= 360;
		vis[loc] = true;
	
	vector<int> ans;
	for(auto it:vis)
		ans.push_back(it.first);
	
	int res = 0;
	sort(ans.begin(),ans.end());
//	cout<<ans.size()<<endl;
	ans.push_back(0);
	for(int i = 1;i <= n + 1; ++i) 
		int k = (ans[i] - ans[i-1] + mod) % mod;
		res = max(res,k);
	
	cout<<res<<endl;
	return 0;

C - digitnum(快速幂+预处理)

题意

我们定义一个 f ( x ) f(x) f(x)为和x位数相同并且小于等于x的数量,然后求 ∑ i = 1 i < = N f ( i ) \\sum_i=1^i<=Nf(i) i=1i<=Nf(i)

思路

我们可以预处理位数减一的所有值,对于位数为1的所有的f(x)求和就是 1 + 2 + 3 + … … + 9 1+2+3+……+9 1+2+3++9,那么同理二位数的就是 1 + 2 + 3 + … … + 89 1+2+3+……+89 1+2+3++89的和,也就是每次减去了某一个特殊值(由1构成的数),然后对于剩下的我们直接再计算一次求和公式就好了

代码

#include<bits/stdc++.h>
using namespace std;
//----------------自定义部分----------------
#define ll long long
#define mod 998244353
#define endl "\\n"
#define PII pair<int,int>
#define INF 0x3f3f3f3f

int dx[4]=0,-1,0,1,dy[4]=-1,0,1,0;

ll ksm(ll a,ll b) 
	ll ans = 1;
	for(;b;b>>=1LL) 
		if(b & 1) ans = ans * a % mod;
		a = a * a % mod;
	
	return ans;


ll lowbit(ll x)return -x & x;

const int N = 2e6+10;
//----------------自定义部分----------------
ll n,m,q,a[N];

ll get_len(ll k)
	ll ans = 0;
	while(k) ans++,k/=10;
	return ans;

ll qpow(ll x, ll n) 
	ll res = 0;
	x%= mod;
	n%= mod;
	while(n) 
		if(n & 1) 
			res = (res + x) % mod;
		
		x = (x%mod + x%mod) % mod;
		n >>= 1;
	
	return res%mod;

ll inv(ll x)
	return ksm(x,mod-2);

ll kkk = inv(2);

ll f(ll num)
	ll len = get_len(num)-1;
	ll ans = 0;
	for(ll i = 1,res = 0,dis = 1;i <= len; ++i,dis=(dis*10)%mod) 
		res = (res * 10 + 9) % mod;
		ll kk = (res - dis + 1 + mod) % mod;
		ans = (ans + (qpow(kk,kk+1) * kkk) % mod) % mod;
	
	return ans;




int main()

	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout.tie(nullptr);
	cin>>n;
	ll l = get_len(n)-1;
	ll ans = f(n);
	ll k = 0;
	while(k < n)
		k = k * 10 + 9;
	
	k/=10;
	n -= k;
	k = (qpow(n,n+1) * kkk) % mod;
	ans = (ans + k) % mod;
	cout<<ans<<endl;
	return 0;

D - AND and SUM(位运算+数学)

题意

给你一个a和s请判断是否有x和y满足下面两个等式:

  • x A N D y = a x AND y = a xANDy=a
  • x + y = s x + y = s x+y=s
    如果有的话请输出Yes,否则输出No

思路

首先我们要明确一件事, X + Y > = 2 a X+Y>=2a X+Y>=2a因为x和y进行与操作后最大就为其中较小值,所以最理想的最大值就是两者相等,也就是说 s > = 2 a s>=2a s>=2a的,然后我们要在计算一下 s − 2 a s-2a s2a的值和a不能出现相同的位数,所以我们进行一个与操作,看是否等于0,如果是等于0的话那么我们就输出Yes否则输出No
这里给一下官方的解释吧:

代码

#include<bits/stdc++.h>
using namespace std;
//----------------自定义部分----------------
#define ll long long
#define mod 1000000007
#define endl "\\n"
#define PII pair<int,int>
#define INF 0x3f3f3f3f

int dx[4]=0,-1,0,1,dy[4]=-1,0,1,0;

ll ksm(ll a,ll b) 
	ll ans = 1;
	for(;b;b>>=1LL) 
		if(b & 1) ans = ans * a % mod;
		a = a * a % mod;
	
	return ans;


ll lowbit(ll x)return -x & x;

const int N = 2e6+10;
//----------------自定义部分----------------
ll t,n,s,a;

int main()

//	std::ios::sync_with_stdio(false);
//	std::cin.tie(nullptr);
//	std::cout.tie(nullptr);
	cin>>t;
	while(t--)
		cin>>a>>s;
		ll k = (a<<1LL);
		if(s >= k) 
			k = s - k;
			if((k & a) == 0) cout<<"Yes"<<endl;
			else cout<<"No"<<endl;
		
		else cout<<"No"<<endl;
	
	return 0;

/*
1
1152921504606846976 2305843009213693952
*/

E - Range Sums(并查集)

题意

输入一个n和q分别表示数组的长度为n,有q次信息,每次信息输入一个l和r,表示我们知道l到r区间的和的信息,问你最后能否求出整个数组的和的信息,如果可以输出Yes否则输出No

思路

我们来思考一下每次的这个信息是啥,其实就是一个不完全的前缀和信息,之所以说它不完全,是因为l不一定是以1为起点的,我们想要求的信息是前n个数的和信息,那么对于这个信息我们需要知道是否有一个链接方式使得从0链接到n,那么对于每一次的信息其实就是一条边,我们从l-1连接到r,最后判断一下0和n是否联通就好了,如果联通的话那么一定能找到一条满足条件的前缀和信息链,反之则不能找到,于是我们可以用并查集维护该信息

代码

#include<bits/stdc++.h>
using namespace std;
//----------------自定义部分----------------
#define ll long long
#define mod 1000000007
#define endl "\\n"
#define PII pair<int,int>
#define INF 0x3f3f3f3f

int dx[4] = -1, 0, 1, 0, dy以上是关于AtCoder Beginner Contest 238的主要内容,如果未能解决你的问题,请参考以下文章

AtCoder Beginner Contest 234

AtCoder Beginner Contest 115 题解

AtCoder Beginner Contest 154 题解

AtCoder Beginner Contest 103

AtCoder Beginner Contest 228

AtCoder Beginner Contest 242