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
s−2a的值和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 115 题解